获取未平仓订单的最大回撤
当一个策略持有一个或多个开仓订单时,我们可以使用 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)。





