这期考个古,写一个几年前S&C杂志上的明星指标。这里简单的介绍下S&C杂志,全称为《股票期货技术分析》,这是一本专注于「技术分析」的杂志,在交易领域享有很高的声誉。

谈到短期跟踪止损指标,ATR算一个,大名鼎鼎的吊灯止损法就是根据ATR指标设计的。它的具体算法是先选定一个时间段比如14天,然后计算这14天每一天的真实波动,也就是当日最高价、最低价和前一日收盘价三者之间的最大值,最后将每日的真实波动值加总,再除以14,就得到了ATR指标。

但是ATR指标有一个很明显的缺点,那就是用小倍数的ATR作为止损指标,止损点会比较接近买入价,因此很容易被市场波动触及,导致很多单子亏损出局那怎么能做到既能在合适的时候止损,又能让利润奔跑呢

在大量尝试实践后,作者设计了一个短期跟踪止损指标——支撑(support)/阻力位(resistance)追踪,简称Tr&nds,这个指标可以称得上S&C杂志近20年的明星指标了。它的优势在于:既能避免价格轻易打到止损线,又能保护已经赚到的利润

作者依次说明了怎样定义关键支撑位、跳空支撑位,然后加入了改进版的ATR,最后得到Tr&nds指标。文中所有代码是用Thinkscript写的,这种语言类似通达信的代码,为了方便大家直接拿来用,我把Thinkscript的代码全部用python写了一遍~

Pivot Support(关键支撑位):我们先检查过去4天的价格是否形成了支撑位。如果前2天的最低价是过去4天中最低的,那么就把前2天的最低价设置为支撑位。如果不满足上述条件,那么支撑位就是上一个周期的值。这一段逻辑定义了支撑位,原文的代码是:

用python写一遍:

1
def pivot_support(df): for i in range(4, df.shape[0]): if df['low'][i] >= df['low'][i-2] and df['low'][i-1] >= df['low'][i-2] and df['low'][i-3] >= df['low'][i-2] and df['low'][i-4] >= df['low'][i-2]: df['support'][i] = df.low[i-2]

我们把定义好的支撑位放到一段股价走势图里,发现加上了支撑位后,确实能更好的跟踪股价走势。但是有个问题,当价格波动幅度很大时,比如图中箭头所指处,跟踪止损就和价格偏差的太远了,怎么处理这种情况呢?

Gap Support(跳空支撑位):

首先,价格波动幅度大的一个表现形式是跳空,而跳空缺口会形成支撑位,作者增加了一段代码,定义了跳空缺口形成的支撑位:在一段上涨趋势里,当前k线的最低价 > 前一根k最高价的0.13%就被定义为“跳空”,支撑位就放在前一根k的最高价*99.45%的位置上,0.13%和99.45%的参数都是作者大量尝试后决定的。

代码如下:

1
def gap_support(df): for i in range(4, df.shape[0]): if df['low'][i] > df['high'][i-1] * 1.0013: df['support'][i] = df['high'][i - 1] * 0.9945

添加了gap support跳空支撑位后,趋势线和价格贴的更紧密了,蓝色箭头是加进去的gap support:

但是跳空支撑位的缺点是会把Common gap考虑进来。Common gap是在震荡区间产生的跳空,一般一周内就会回补,因此这种缺口的支撑位没有多大用处。

在西方交易界,跳空被定义为几种类型:

图中可以看到,这种common gap出现在震荡区间,缺口在短时间内会回补,因此这种gap对交易没什么指导意义。作者在后文中对此给出了解决方案,那就是制定了最高价卖出规则——当且仅当最高价跌穿跟踪线才卖出

除了跳空高开外,紧密衔接的连续上涨走势也是价格大幅波动的表现形式,这种情况会导致我们的跟踪止损远远偏离价格走势

这种情况怎么办呢?我们继续写一段代码,如果(当前的最低价)大于(前一天的support乘以1.1),那么就把前一天的support乘以1.05作为当前的支撑位。

1
def support(df): for i in range(4, df.shape[0]): if df['low'][i] > df['support'][i-1] * 1.1: df['support'][i] = df['support'][i - 1] * 1.05

在下面这幅连续上涨的价格走势图中,可以看到蓝色箭头标注位置的跟踪止损线和价格亦步亦趋,贴的更紧了。

比如在下面这个价格走势图中,EXIT的位置是出场位置,我们看到出场的那根K线的最高价跌穿了跟踪止损。

上面定义了支撑位,到这里离Tr&nds指标出炉还有一步之遥啦。作者接下来加入了改进版的ATR指标,用于回避下跌行情,作者在前几期文章中讲了改进版ATR的构造原理,由于篇幅有限,这里就不展开介绍了。

把所有代码合并一起,我们得到了最终指标的代码:

1
# data是BTC的OLHCVM数据,也就是包含开盘价、收盘价、最高和最低价、成交量的数据 def support(df): for i in range(4, df.shape[0]): if df['low'][i] >= df['low'][i-2] and df['low'][i-1] >= df['low'][i-2] and df['low'][i-3] >= df['low'][i-2] and df['low'][i-4] >= df['low'][i-2]: df['support'][i] = df.low[i-2] elif df['low'][i] > df['high'][i-1] * 1.0013: df['support'][i] = df['high'][i - 1] * 0.9945 elif df['low'][i] > df['support'][i-1] * 1.1: df['support'][i] = df['support'][i - 1] * 1.05 else: df['support'][i] = df['support'][i-1] return df def resistance(df): df['H-L'] = df['high'] - df['low'] df['SMA'] = df['H-L'].rolling(window=10).mean() df['HiLo'] = np.where(df['H-L'] < 1.5 * df['SMA'], df['H-L'], 1.5 * df['SMA']) # 计算Href和Lref值 df['Href'] = np.where(df['low'] <= df['high'].shift(-1), df['high'] - df['close'].shift(-1), (df['high'] - df['close'].shift(-1)) - (df['low'].shift(-1) - df['high'].shift(-1)) / 2) df['Lref'] = np.where(df['high'] >= df['low'].shift(-1), df['close'].shift(-1) - df['low'], (df['close'].shift(-1) - df['low']) - (df['low'].shift(-1) - df['high'].shift(-1)) / 2) # 计算diff1、diff2和ATRmod值 df['diff1'] = np.maximum(df['HiLo'], df['Href']) df['diff2'] = np.maximum(df['diff1'], df['Lref']) df['ATRmod'] = df['diff2'].ewm(alpha=1 / 10, adjust=False).mean() # 计算resistance值 df['loss'] = 2.8 * df['ATRmod'] df['resistance'] = df['close'] + df['loss'] return df def trends(df): for i in range(1, df.shape[0]): if df['high'][i] > df['support'][i-1] and df['high'][i-1] > df['support'][i-1]: df['trends'][i] = max(df['support'][i-1], df['support'][i]) elif df['high'][i] < df['support'][i-1] and df['high'][i-1] < df['support'][i-1]: df['trends'][i] = min(df['support'][i-1], df['resistance'][i]) elif df['high'][i] >= df['support'][i-1]: df['trends'][i] = df['support'][i] else: df['trends'][i] = df['resistance'][i] return df

最后,作者定义了买卖规则:当最高价高于Tr&nds➡️买入,当最高价跌穿Tr&nds➡️卖出,然后测试了28只股票,表中只给了净利润和交易次数,而且年代有些久远了:

那这个改进后的ATR到底好不好用呢?是骡子是马,我们牵出来616(遛一遛)。

选取1971-2023纳斯达克的日线数据,回测结果如下:

选取2010-2023特斯拉股票的日线数据,回测结果如下:

从纳指和特斯拉的回测看来,Tr&nds指标在最大回撤(Maximum Drawdown)为81%的情况下,依然实现了0.75和0.77的夏普比率。回测宁德时代2019-2023日线数据:

通过几个品种的回测,我们可以大致得出几个结论:

1.这个指标在不同品种上的表现不同,如果要使用该指标,品种筛选过滤是必须的。

2.作者给的简单买卖规则是不够的,要加入其他信号和仓位管理

3.因为这是一个改进版的ATR指标,而ATR更多被用于跟踪止盈止损,所以这个指标用于平仓可能比开仓更好

原文网盘通过百度网盘分享的文件:3__V27_C…链接:https://pan.baidu.com/s/1INbM4nhnqfh9MThziC0xjg?pwd=8888

提取码:8888复制这段内容打开「百度网盘APP 即可获取」


欢迎关注puppy的个人公众号:

跟puppy玩量化

写点对投资交易有用的东西~

另外还有一个quant小群,欢迎加入~