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

Pine Script(230):未平仓订单的最大回撤max_drawdown

#Pine Script入门教学

获取未平仓订单的最大回撤

当一个策略持有一个或多个开仓订单时,我们可以使用 strategy.opentrades.max_drawdown() 函数来获取某一个特定开仓订单的最大回撤。这个最大回撤指的是该笔订单自开仓以来,到当前K线为止,所经历过的历史最大亏损。

我们可以通过多种方式来利用这个最大回撤值,例如:计算所有开仓订单的平均最大回撤;如果每笔订单都在其最大回撤点平仓,计算整个仓位的最大可能亏损;通过将其与当前浮动盈利进行比较,看每个订单从最大回撤中恢复了多少;将每个订单的最大回撤与其最大浮动盈利进行对比,以粗略评估其风险回报比;模拟在市场波动性(如ATR所示)增加一倍的情况下,订单的最大回撤可能会是多少。

默认语法结构

该函数的标准语法如下:

strategy.opentrades.max_drawdown(trade_num)

trade_num 是开仓订单的编号。这个整数用于告知PineScript我们想要获取哪一笔开仓订单的最大回撤值。这个订单编号采用从零开始的索引方式:第一笔开仓订单的编号是0,第二笔是1,第三笔是2,以此类推。我们可以通过 strategy.opentrades - 1 这个表达式来获取最后一笔(即最新一笔)订单的编号。

这个函数的返回值有两种可能:一是返回一个正的浮点数,代表指定开仓订单的最大回撤(即最大潜在亏损);二是返回 na 值,这在传入的订单编号 trade_num 不正确(例如小于0,或大于等于当前开仓订单的总数 strategy.opentrades),或者策略当前没有任何持仓时会发生。

快速示例

要获取第一笔开仓订单(即最早的那一笔)的最大回撤,我们可以这样做:

// 检索持仓中第一笔入场的最大回撤
firstEntryDrawdown = strategy.opentrades.max_drawdown(0)

要获取最后一笔开仓订单(即最新的一笔)的最大回撤,可以这样使用:

// 获取最新一笔入场的最大回撤值
lastEntryDrawdown = strategy.opentrades.max_drawdown(strategy.opentrades - 1)

另一个应用场景是遍历所有开仓交易。例如,假设我们想计算所有开仓订单的平均最大回撤。我们可以创建一个 for 循环,遍历所有订单,将它们的最大回撤值累加起来,最后再除以订单总数。代码示例如下:

// 首先,累加每个开仓订单的最大回撤值
entryDrawdownSum = 0.0
for tradeNumber = 0 to strategy.opentrades - 1
    entryDrawdownSum += strategy.opentrades.max_drawdown(tradeNumber)

// 计算所有当前开仓交易的平均回撤
avgDrawdown = entryDrawdownSum / strategy.opentrades

函数的特性

最大回撤值包含了订单的手续费成本。因此,策略的手续费越高,一个开仓订单的最大回撤值就越大。

此函数返回的是订单迄今为止最大潜在亏损的一个快照。由于订单尚未平仓,这个回撤值在未来仍有可能继续增加(变得更糟),但它不可能减小,因为它记录的是已经发生过的最大值。

特别要注意:strategy.opentrades.max_drawdown() 返回的最大回撤是一个正数,而不是负数,它代表的是亏损的幅度。此外,此函数测量的回撤是从入场价格到后续的最差价格(对多头是最低价,对空头是最高价),而不是从交易过程中的浮动盈利最高点到最低点的回撤。

这个函数是自PineScript版本5起才可用的新功能,在版本4及更早的版本中不存在,且只能在策略(strategy)脚本中使用,不能在指标(indicator)中使用。

示例策略

让我们通过一个完整的策略来看看如何使用 strategy.opentrades.max_drawdown() 函数。下方的脚本基于EMA和SMA的交叉进行交易。当快线穿过慢线时,策略会顺着交叉方向开仓。当持仓时,如果价格再次穿越快线,策略会进行加仓。

在每个K线上,策略都会使用 strategy.opentrades.max_drawdown() 计算整个仓位的总最大回撤。然后,代码会判断这个总回撤是否比上一根K线时更大了。如果是,策略就会将图表背景涂成红色以作警示。

策略的完整代码如下:

//@version=5
strategy(title="开仓交易的最大回撤", pyramiding=2, overlay=true)

// 计算并绘制EMA和SMA
emaValue = ta.ema(close, 20)
smaValue = ta.sma(close, 50)
plot(emaValue, color=color.orange, title="EMA")
plot(smaValue, color=color.teal, linewidth=2, title="SMA")

// 根据EMA-SMA交叉生成初始入场
if ta.crossover(emaValue, smaValue)
    strategy.entry("Enter Long 1", strategy.long)
if ta.crossunder(emaValue, smaValue)
    strategy.entry("Enter Short 1", strategy.short)

// 根据EMA交叉触发额外入场(加仓)
if strategy.position_size > 0 and ta.crossover(close, emaValue)
    strategy.entry("Enter Long 2", strategy.long)
if strategy.position_size < 0 and ta.crossunder(close, emaValue)
    strategy.entry("Enter Short 2", strategy.short)

// 计算当前持仓的总最大回撤
positionMaxDD = 0.0
for tradeNumber = 0 to strategy.opentrades - 1
    positionMaxDD += strategy.opentrades.max_drawdown(tradeNumber)

// 当持仓创下新的最大回撤时,将图表背景涂成红色
newMaxDD = strategy.openprofit < 0 and 
     positionMaxDD > positionMaxDD[1]
bgcolor(newMaxDD ? color.new(color.red, 80) : na)

我们首先配置策略并计算绘制了两条均线。开仓逻辑包括初始的均线金叉/死叉入场,以及后续的加仓逻辑。

接着,我们计算当前持仓的总最大回撤:

// 计算当前持仓的总最大回撤
positionMaxDD = 0.0
for tradeNumber = 0 to strategy.opentrades - 1
    positionMaxDD += strategy.opentrades.max_drawdown(tradeNumber)

这段代码初始化了一个 positionMaxDD 变量,然后通过 for 循环遍历所有开仓订单,将每一笔订单的最大回撤值累加起来,从而得到整个仓位的总最大回撤。

最后,我们判断这个最大回撤是否恶化了:

// 当持仓创下新的最大回撤时,将图表背景涂成红色
newMaxDD = strategy.openprofit < 0 and 
     positionMaxDD > positionMaxDD[1]
bgcolor(newMaxDD ? color.new(color.red, 80) : na)

我们创建一个布尔变量 newMaxDD。它的值为真的条件有两个:第一,当前仓位是亏损的(strategy.openprofit < 0);第二,当前K线的总最大回撤大于上一根K线的值。当条件满足时,我们就通过 bgcolor() 函数将图表背景设为半透明的红色。

在图表上,每当策略的持仓创下新的最大回撤记录时(对多头是价格创新低,对空头是价格创新高),背景就会被涂成红色,从而直观地警示我们亏损正在扩大:

简单总结一下:strategy.opentrades.max_drawdown() 函数返回某一个特定开仓订单的最大回撤,即该订单自开仓以来所经历的最大亏损。我们通过一个订单编号来告知函数我们想要查询哪一笔订单,第一个订单的编号是0,最后一笔(最新一笔)订单的编号是 strategy.opentrades - 1。该函数返回的最大回撤是一个正数,且是包含了手续费成本之后的数值。

理解订单的最大回撤

PineScript中有两个函数可以返回一个订单的最大回撤(Maximum Drawdown):strategy.opentrades.max_drawdown() 返回一个当前持仓订单到目前为止的最大回撤;strategy.closedtrades.max_drawdown() 返回一个已平仓订单在其整个生命周期中的最大回撤。

这很好,但这个最大回撤值究竟是什么意思呢?

最大回撤指的是一个订单在其持有期间所发生过的最大浮动亏损。它代表了这笔交易最糟糕的可能结果。

最大回撤告诉我们,如果我们恰好在最不利的价格点平仓,订单会是什么结果。通常情况下,一笔交易的最终盈亏会比其最大回撤要好。通过比较这两个指标,我们可以看出交易从亏损低点恢复了多少。此外,如果我们将最大回撤与最大浮盈进行比较,就能大致了解这笔交易的风险(回撤)与回报(浮盈)。

如何衡量订单回撤

要衡量一个订单的回撤,我们需要用其入场价与最差价格之间的价差,乘以订单的大小,然后再加上佣金成本。

这里的最差价格,对于多头订单来说,是指订单持有期间的最低价;对于空头订单来说,则是指订单持有期间的最高价。

图表示例

让我们通过一个例子来进一步说明。对于一个多头订单,其最大回撤值是(入场价 – 最低价)× 订单大小 + 佣金。在图表上它看起来是这样的:

这个多头订单在7337.27开仓。在订单持有期间,价格最低达到了7309.19。这带来了每个合约28.08点的浮动亏损。由于该订单买入了5个合约,其最大回撤是140.40美元(5 x 28.08)。

现在我们再来看看空头的情况。对于一个空头订单,其最大回撤是(最高价 – 入场价)× 订单大小 + 佣金。下面是一个图表示例:

这个空头订单在7236.47开仓。在订单持有期间,该交易品种最高达到了7307.78。这造成了每个合约71.31点的潜在亏损。由于该策略做空了5个合约,此订单的最大回撤值是356.55美元(5 x 71.31)。

(为了避免问题复杂化,以上两个例子都没有计算佣金。如果计算了佣金,最大回撤值会因5个合约的交易成本而变得更大。)

最大回撤的特性

理想情况下,我们希望策略中订单的平均最大回撤较小。一个较高的平均最大回撤通常意味着很多订单会被止损出局,或者反过来说,策略需要一个很宽的止损才能生存。

要注意的是,一个订单的最大回撤是从入场价到最差价格的距离。它衡量的是资金的回撤,而不是衡量浮动利润的回撤——后者的定义是从盈利的最高点回落到后续最低点的距离。通常,浮动利润的回撤会比基于入场价的资金回撤要大。

另外,一个订单的最终盈亏总是等于或优于其最大回撤值。因为最大回撤已经捕捉到了最坏的可能结果,所以最终亏损不可能比这个值更大。

strategy.opentrades.max_drawdown()strategy.closedtrades.max_drawdown() 这两个函数的计算方式完全相同。它们唯一的区别在于:前者报告的是持仓订单到目前为止的初步最大回撤,而后者报告的是已平仓订单在其整个生命周期中的最终最大回撤。

除了单个订单的最大回撤,我们也可以衡量一个总仓位的最大回撤,只需将构成该仓位的每个订单的最大回撤相加即可。

最大不利偏移(Maximum Adverse Excursion)

在交易文献中,PineScript中所说的订单最大回撤值,也被称为最大不利偏移(Maximum Adverse Excursion,MAE)。

最大不利偏移被定义为入场价与交易期间最不利价格之间的差值。对于多头,MAE是入场价与最低价之间的差值;对于空头,则是入场价与最高价之间的差值。

与订单的最大回撤值一样,MAE衡量的也是一笔交易在其生命周期中向不利方向发展的最大幅度。

简单总结一下:一个订单的最大回撤值是其可能出现的最差亏损。它的计算方式是用最差价格(多头为最低价,空头为最高价)与入场价的价差,乘以订单大小,再加上佣金成本。最大回撤越高,说明订单经历的不利价格波动越大。一个订单的最大回撤也被称为最大不利偏移(MAE)。

赞(0)
未经允许不得转载:图道交易 » Pine Script(230):未平仓订单的最大回撤max_drawdown
分享到

评论 抢沙发

登录

找回密码

注册