🏠
AI量化交易 · 第18章:趋势跟踪策略
目录
Chapter 18

趋势跟踪

让利润奔跑——搭上市场大趋势的顺风车

本章学习目标

你将学会

  1. 理解趋势跟踪的核心哲学和底层逻辑
  2. 掌握唐奇安通道、ATR等趋势跟踪经典工具
  3. 学会用Backtrader实现海龟交易策略
  4. 了解趋势跟踪策略的回撤特征和资金管理
  5. 能够用AI辅助优化趋势跟踪参数

趋势跟踪是量化交易中最古老、最被验证有效的策略流派之一。它的理念简单到令人难以置信:价格上涨时买入,价格下跌时卖出。但就这么一句"废话",却造就了无数亿万富翁。

故事引入:海龟们的传奇

1983年,两位华尔街传奇人物——理查德·丹尼斯和威廉·埃克哈特——打了一个赌。

丹尼斯认为,交易是可以教会的,成功的交易者不是天生的,而是培养出来的。埃克哈特则认为,交易天赋是与生俱来的,无法通过教学获得。

为了验证谁对谁错,丹尼斯在报纸上刊登广告,招募了一群完全没有交易经验的普通人——包括一个游戏设计师、一个会计师、一个服务员。他给这些人两周的密集培训,教给他们一套简单的趋势跟踪规则,然后每人发了一笔钱去实盘交易。

这套规则后来被称为"海龟交易法则"。核心就三条:

  1. 入场:当价格突破过去20日高点时买入
  2. 仓位:根据ATR计算,每笔交易风险不超过总资金的2%
  3. 出场:当价格跌破过去10日低点时卖出

结果如何?这群"海龟"在随后的四年里,创造了年均80%以上的复利回报。其中一些人后来成立了自己的对冲基金,管理数十亿美元。

海龟实验证明了什么?交易成功不取决于智商、学历或内幕消息,而取决于是否有一套纪律严明的规则,以及能否坚持执行它。这正是量化交易的核心精神。

核心知识:趋势跟踪的量化密码

2.1 趋势跟踪的底层哲学

趋势跟踪的理论基础是价格动量的持续性。也就是说,涨了一段时间的股票,短期内继续上涨的概率略高于下跌的概率。这听起来像"追涨杀跌",但在统计学上确有支撑。

为什么会有趋势?行为金融学给出了几个解释:

趋势跟踪者不关心趋势形成的原因,只关心趋势是否存在。就像冲浪者不关心浪从哪里来,只关心浪在哪里。

2.2 唐奇安通道:捕捉趋势的网

唐奇安通道(Donchian Channel)是海龟策略的核心工具。它非常简单:

上轨 = 过去N日的最高价
下轨 = 过去N日的最低价
中轨 = (上轨 + 下轨) / 2

海龟策略用20日通道突破作为入场信号10日通道突破作为出场信号。这种"长周期入场、短周期出场"的设计非常精妙:它让策略能够捕捉到大的趋势行情,同时在趋势反转时快速离场。

flowchart LR A[计算20日最高价] --> B{价格突破?} B -->|是| C[买入开仓] B -->|否| D[继续等待] C --> E[计算10日最低价] E --> F{价格跌破?} F -->|是| G[卖出平仓] F -->|否| H[持有让利润奔跑] H --> E style C fill:#10b981,color:#fff style G fill:#e74c3c,color:#fff style B fill:#f97316,color:#fff

2.3 ATR:衡量市场波动的尺子

平均真实波幅(Average True Range, ATR)是海龟策略中用于仓位管理的关键指标。它回答的问题是:这只股票平均每天波动多少?

真实波幅(TR) = max(当日最高-最低, |当日最高-昨日收盘|, |当日最低-昨日收盘|)

ATR = 过去N日TR的移动平均(通常N=20)

ATR的核心用途:

2.4 海龟策略的仓位管理:N值系统

海龟策略的仓位管理是其最精妙的部分。它把资金分成若干"单位",每个单位的风险严格控制在总资金的2%。

PYTHON
"""
海龟策略核心逻辑 - 简化版
"""
import backtrader as bt

class TurtleStrategy(bt.Strategy):
    params = (
        ('entry_period', 20),    # 入场通道周期
        ('exit_period', 10),     # 出场通道周期
        ('atr_period', 20),      # ATR计算周期
        ('risk_pct', 0.02),      # 每笔风险2%
        ('atr_multiplier', 2),   # 止损 = 入场价 - N*ATR
    )
    
    def __init__(self):
        # 唐奇安通道
        self.donchian_high = bt.indicators.Highest(
            self.data.high, period=self.p.entry_period
        )
        self.donchian_low = bt.indicators.Lowest(
            self.data.low, period=self.p.exit_period
        )
        
        # ATR
        self.atr = bt.indicators.ATR(period=self.p.atr_period)
        
        self.order = None
        self.entry_price = None
        self.position_size = 0
    
    def calculate_unit_size(self):
        """
        计算1个交易单位的股数
        公式: 单位股数 = (账户资金 * 风险比例) / (ATR * ATR倍数)
        """
        cash = self.broker.getvalue()
        risk_amount = cash * self.p.risk_pct
        stop_distance = self.atr[0] * self.p.atr_multiplier
        
        if stop_distance == 0:
            return 0
        
        unit_size = int(risk_amount / stop_distance)
        return unit_size
    
    def next(self):
        if self.order:
            return
        
        # 出场逻辑(优先)
        if self.position:
            if self.data.close[0] < self.donchian_low[0]:
                self.order = self.sell(size=self.position.size)
                return
        
        # 入场逻辑
        if not self.position:
            if self.data.close[0] > self.donchian_high[-1]:
                self.position_size = self.calculate_unit_size()
                if self.position_size > 0:
                    self.order = self.buy(size=self.position_size)
    
    def notify_order(self, order):
        if order.status in [order.Completed]:
            if order.isbuy():
                self.entry_price = order.executed.price
                print(f'海龟买入: {self.position_size}股 @ {order.executed.price:.2f}')
            else:
                pnl = (order.executed.price - self.entry_price) * order.executed.size
                print(f'海龟卖出: {order.executed.price:.2f}, 盈亏: {pnl:.2f}')
                self.entry_price = None
        self.order = None

2.5 趋势跟踪者的"痛苦":低胜率与高盈亏比

趋势跟踪策略有一个反直觉的特征:胜率通常很低,只有30%-40%,但盈亏比很高,平均盈利是平均亏损的2-3倍。

这意味着趋势跟踪者的大部分交易都是亏损的。他们依靠少数几次大趋势交易来覆盖所有小额亏损并实现盈利。就像钓鱼:你抛竿十次,可能九次空竿,但钓到的那一条可能是大鱼。

这种特征对交易者的心理是巨大的考验。连续七八次亏损后,你还敢执行第九次信号吗?大多数人不敢。但正是这种心理门槛,让趋势跟踪策略的Alpha能够持续存在——因为它太反人性了

科学争议:趋势跟踪已经失效了吗?

正方:从2009年到2020年的美股长牛中,趋势跟踪策略确实表现不佳,因为它频繁在小幅回调中被震出。但这只是十一年间的表现。把时间拉长到五十年,趋势跟踪在应对大熊市(如2000年、2008年)时的保护作用无可替代。趋势跟踪不是每天都赚钱,而是在关键时刻救命

反方:央行干预改变了市场结构。量化宽松让资产价格单向上涨,波动率被人为压低,传统的趋势信号大量失效。在"永远涨"的市场中,买入持有比趋势跟踪更优。

量化交易者的务实态度:不预测市场结构会不会变,而是把趋势跟踪作为多策略组合的一部分,分配合理的权重。同时,用波动率过滤(如只在VIX>20时启用趋势跟踪)来提高策略的适应性。

2.6 趋势强度过滤:只在强趋势中交易

一个改进思路是:不是所有突破都值得跟,只跟"强趋势"的突破。衡量趋势强度的常用指标是ADX(平均趋向指数)

把ADX作为过滤条件加入海龟策略,可以显著减少震荡市中的假信号。代价是会错过一些趋势初期的机会。

2.7 多品种分散:趋势跟踪的免费午餐

海龟策略的另一个精髓是同时在多个不相关的市场中交易。股票、债券、商品、外汇、期货——当某个市场没有趋势时,另一个市场可能正在爆发。

对于A股个人投资者,虽然无法直接投资期货和外汇,但可以通过ETF实现跨资产分散:沪深300ETF(股票)、国债ETF(债券)、黄金ETF(商品)。当股票市场震荡时,黄金可能正在走出趋势。

与AI一起练习

练习1:让AI写完整的海龟策略

Prompt模板

PROMPT
请用Backtrader实现一个完整的海龟交易策略,要求:
1. 入场:价格突破20日高点时买入
2. 出场:价格跌破10日低点时卖出
3. 仓位:根据20日ATR计算,每笔交易风险不超过资金的2%
4. 止损:入场价 - 2倍ATR
5. 添加ADX过滤:ADX>25时才允许入场
6. 使用AKShare获取沪深300ETF(510300)数据回测
7. 输出夏普比率、最大回撤、胜率、盈亏比

练习2:让AI对比不同参数的海龟策略

Prompt模板

PROMPT
请对比以下几组海龟策略参数在A股的表现:
- 短海龟:10日入场/5日出场
- 经典海龟:20日入场/10日出场
- 长海龟:55日入场/20日出场

要求用表格对比以下指标:
- 总收益率
- 最大回撤
- 胜率
- 盈亏比
- 交易次数
- 平均持仓天数

并分析:哪组参数最适合A股市场的特点?

练习3:让AI给海龟策略加过滤器

Prompt模板

PROMPT
请为海龟策略添加以下过滤条件,解释每个条件的作用:
1. 只在价格高于200日均线时做多(避免逆势交易)
2. 只在ADX>20时入场(避免震荡市)
3. 如果过去5日波动率超过过去20日波动率的2倍,暂停入场(避免极端波动)

请给出修改后的完整代码。

动手实践:海龟策略模拟器

下面这个交互式模拟器可以帮助你理解海龟策略的仓位计算逻辑。调整参数,观察仓位和风险的变化:

海龟仓位计算器

单位股数: 2000股
止损价位: 90.00元
单笔风险: 2.00万元
建议最大持仓单位: 4个

下面的代码是一个完整的海龟策略回测模板,你可以直接复制运行:

PYTHON
"""
海龟策略完整版 - 含ADX过滤和ATR仓位管理
"""
import backtrader as bt
import akshare as ak
import pandas as pd

class TurtleStrategy(bt.Strategy):
    params = (
        ('entry_period', 20),
        ('exit_period', 10),
        ('atr_period', 20),
        ('risk_pct', 0.02),
        ('atr_mult', 2),
        ('adx_period', 14),
        ('adx_filter', 25),
    )
    
    def __init__(self):
        self.donchian_high = bt.ind.Highest(self.data.high, period=self.p.entry_period)
        self.donchian_low = bt.ind.Lowest(self.data.low, period=self.p.exit_period)
        self.atr = bt.ind.ATR(period=self.p.atr_period)
        self.adx = bt.ind.AverageDirectionalMovementIndex(period=self.p.adx_period)
        self.order = None
    
    def calculate_size(self):
        cash = self.broker.getvalue()
        risk_amount = cash * self.p.risk_pct
        stop_dist = self.atr[0] * self.p.atr_mult
        return int(risk_amount / stop_dist) if stop_dist > 0 else 0
    
    def next(self):
        if self.order: return
        
        if self.position:
            if self.data.close[0] < self.donchian_low[0]:
                self.order = self.sell(size=self.position.size)
            return
        
        if (self.data.close[0] > self.donchian_high[-1] and 
            self.adx[0] > self.p.adx_filter):
            size = self.calculate_size()
            if size > 0:
                self.order = self.buy(size=size)
    
    def notify_order(self, order):
        if order.status in [order.Completed]:
            self.order = None

if __name__ == "__main__":
    cerebro = bt.Cerebro()
    cerebro.addstrategy(TurtleStrategy)
    cerebro.broker.setcash(100000.0)
    cerebro.broker.setcommission(commission=0.0003)
    
    # 请替换为实际数据加载代码
    # df = ak.stock_zh_a_hist(...)
    # data = bt.feeds.PandasData(dataname=df, ...)
    # cerebro.adddata(data)
    
    cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe')
    cerebro.addanalyzer(bt.analyzers.DrawDown, _name='dd')
    
    results = cerebro.run()
    strat = results[0]
    print(f'最终资金: {cerebro.broker.getvalue():.2f}')
    print(f"夏普: {strat.analyzers.sharpe.get_analysis().get('sharperatio','N/A')}")
    print(f"最大回撤: {strat.analyzers.dd.get_analysis().max.drawdown:.2f}%")

知识自测

快速检验你的理解
1. 海龟策略的核心入场信号是什么?
  • 价格突破过去20日最高价
  • 短期均线上穿长期均线
  • MACD金叉
  • RSI从超卖区回升
  • 海龟策略使用唐奇安通道突破作为入场信号:当价格突破过去N日(通常是20日)的最高价时买入,这是典型的趋势跟踪逻辑。
    2. ATR在海龟策略中的主要作用是什么?
  • 判断趋势方向
  • 计算入场时机
  • 衡量波动率以确定仓位大小
  • 预测未来价格
  • ATR(平均真实波幅)衡量的是市场的波动性。在海龟策略中,ATR用于计算每笔交易的仓位大小:高波动股票分配小仓位,低波动股票分配大仓位,从而使每笔交易的风险相同。
    3. 趋势跟踪策略的典型特征是什么?
  • 高胜率、低盈亏比
  • 低胜率、高盈亏比
  • 高胜率、高盈亏比
  • 低胜率、低盈亏比
  • 趋势跟踪策略的胜率通常只有30%-40%,但盈亏比可以达到2:1甚至3:1。它依靠少数几次大趋势交易覆盖多次小额亏损,这是其反人性的核心特征。
    4. 为什么趋势跟踪策略在多品种分散时表现更好?
  • 不同市场的趋势不会同时消失,分散降低了空仓期
  • 多品种交易手续费更低
  • 品种越多胜率越高
  • 监管机构要求分散投资
  • 趋势跟踪的致命弱点是"震荡期亏损"。当在多个不相关的市场中同时交易时,总有一些市场处于趋势中,可以弥补其他市场的亏损。这是量化交易中真正的"免费午餐"——分散化带来的收益提升。

    下一章预告

    趋势跟踪的核心是"顺势而为",但市场并非总是处于趋势中。在震荡市中,趋势跟踪者会被反复打脸。那有没有一种策略,专门在震荡市中赚钱呢?

    答案是:均值回归策略。它的理念与趋势跟踪截然相反——当价格偏离正常水平时,押注它会回归。下一章《均值回归策略——高抛低吸的数学表达》,我们将探索这个与趋势跟踪"互补"的策略流派。你会学到布林带均值回归、RSI超卖反弹、配对交易等经典策略。准备好体验"反趋势"交易的魅力了吗?

    课后行动清单
    1. 运行海龟代码:在你的环境中运行海龟策略回测
    2. 对比参数:分别用10日/20日/55日入场周期回测,观察结果差异
    3. 加入ADX过滤:对比有无ADX过滤时的交易次数和胜率
    4. 心理演练:假设你连续亏损7次,第8次信号出现时,你会执行吗?写下来你的答案

    觉得有收获?分享给同样对量化交易感兴趣的朋友

    上一章
    策略的骨架——入场、出场、仓位、止损
    掌握策略的四大核心组件,设计完整的交易规则
    下一章
    均值回归策略——高抛低吸的数学表达
    探索与趋势跟踪互补的反趋势策略体系

    如果这本书对你有所启发,欢迎支持我继续创作

    赞赏二维码