海龟交易法则 (Turtle Trading Strategy) 深入解析

海龟交易法则 (Turtle Trading Strategy) 深入解析

海龟交易法则并非一个单一的技术“指标”,而是一个完整的、机械化的趋势跟踪交易系统。它由传奇交易员理查德·丹尼斯(Richard Dennis)和威廉·埃克哈特(William Eckhardt)在1980年代初提出并用于培训一组被称为“海龟”的新手交易员,并取得了巨大成功。

该策略的核心思想是:市场的大部分利润来自于捕捉并持有大的趋势,通过严格的规则来入场、加仓、止损和出场,消除人为情绪的干扰。

1. 核心组成部分

海龟系统主要包含以下几个关键要素:

  • 市场与时间周期: 最初应用于流动性好的期货市场(商品、货币、利率等),主要基于日线数据。
  • 入场信号 (Breakouts):
    • 系统一 (S1 - 短周期): 当价格突破过去 20天 的最高价时,买入一个单位(Unit);当价格跌破过去 20天 的最低价时,卖出一个单位。
    • 系统二 (S2 - 长周期): 当价格突破过去 55天 的最高价时,买入一个单位;当价格跌破过去 55天 的最低价时,卖出一个单位。
    • 过滤规则: 如果上一次的突破(无论是S1还是S2触发的)是盈利的,则忽略当前的S1入场信号(避免在趋势末期或盘整初期反复入场)。S2信号始终有效。 (注:这是原始规则之一,后续实践中可能被修改或简化)
  • 仓位规模 (Position Sizing): 这是海龟法则的精髓,基于波动性调整仓位大小。
    • 波动性衡量 (N): 使用真实波幅均值 (ATR - Average True Range) 来衡量市场的日均波动。N通常基于20天的ATR计算。
      • TR = Max(High - Low, abs(High - PrevClose), abs(Low - PrevClose))
      • N = ATR(20) = SMA(TR, 20) (原始海龟使用一种特殊的指数加权平均,但SMA或EMA(20)常用作近似)
    • 单位 (Unit): 一个交易单位的大小,使得当价格向不利方向移动 1N 时,账户损失约为账户净值的1% (或预设的其他风险百分比,如0.5%或2%)。
      • Dollar Volatility per point = N * PointValue (PointValue 是每点价格变动代表的美元价值,如原油期货1点=1000美元)
      • Unit Size = (AccountSize * Risk%) / Dollar Volatility per point
      • 计算出的Unit Size通常向下取整为合约张数。
    • 意义: 市场波动大时,每个单位的合约数量减少;波动小时,合约数量增加。确保单笔交易的初始风险相对恒定。
  • 加仓 (Pyramiding): 在初始入场后,如果价格朝着有利方向移动 0.5N,则加仓一个单位。继续按0.5N的间隔加仓,但有总仓位上限(通常是4或5个单位)。
  • 止损 (Stop Loss):
    • 初始止损: 对于任何一个单位,其止损位设置在距离入场价 2N 的反向位置。例如,多头入场价为P,止损设在 P - 2N;空头入场价P,止损设在 P + 2N。
    • 动态调整: 当加仓时,所有单位的止损位可能会被向上(多头)或向下(空头)移动,通常以最新加仓单位的止损位为准,或保持一定距离(如最后入场价 - 2N)。这有助于保护已有利潤。 (注:具体止损调整规则有不同版本)
  • 出场信号 (Exits):
    • 系统一 (S1): 多头头寸在价格跌破过去 10天 最低价时退出;空头头寸在价格突破过去 10天 最高价时退出。
    • 系统二 (S2): 多头头寸在价格跌破过去 20天 最低价时退出;空头头寸在价格突破过去 20天 最高价时退出。
    • 止损退出: 如果价格触及任何单位的止损位,则立即退出该单位(在某些版本中是退出所有头寸)。

2. 海龟策略的优点与局限性

  • 优点:
    • 系统性、纪律性强: 完全基于规则,排除情绪干扰。
    • 能抓住大趋势: 核心是趋势跟踪,一旦抓住趋势,利润可能非常可观。
    • 风险管理明确: 基于波动性的仓位管理和明确的止损规则是其核心优势。
    • 普适性: 理论上可应用于任何有趋势性的市场。
  • 局限性:
    • 在盘整市表现糟糕: 趋势跟踪策略在没有明显趋势的市场中会频繁产生“Whipsaw”(拉锯)信号,导致连续小额亏损。
    • 胜率通常不高: 依赖少数几次大的盈利来弥补多次小的亏损。这在心理上难以承受。
    • 回撤可能很大: 在抓住大趋势之前,可能经历较长时间的亏损或盘整期。
    • 滞后性: 基于历史价格突破,入场点可能已经远离趋势的起点,出场点也可能滞后于趋势的转折点。

将海龟逻辑与其他指标结合构建CTA策略

原始海龟系统是自成体系的,但其核心思想(趋势突破、波动性管理)可以被借鉴,并尝试与其他指标结合以期改善其表现,尤其是在过滤假突破或适应不同市场环境方面。

结合思路:

  1. 使用趋势过滤指标 (如 MA, MACD, ADX) 确认趋势:

    • 目的: 减少在盘整市中的交易次数,只在指标确认存在趋势时才启用海龟的突破信号。
    • 策略示例:
      • MA过滤: 仅当价格位于长期移动平均线(如100日或200日EMA)之上时,才接受海龟系统的做多突破信号;仅当价格位于长期MA之下时,才接受做空突破信号。
      • ADX过滤: 仅当ADX(平均动向指数)高于某个阈值(如20或25),表明市场处于趋势状态时,才启用海龟的突破信号。ADX低于阈值时,暂停交易或切换到其他策略(如均值回归)。
    • 优点: 可能有效过滤掉大量盘整市中的假突破信号,提高胜率。
    • 缺点: 可能错过趋势的早期启动阶段(因为需要等待MA或ADX确认),增加滞后性。
  2. 使用动量指标 (如 RSI, Stochastics) 确认突破强度:

    • 目的: 在突破发生时,利用动量指标确认背后是否有足够的力量支撑趋势继续。
    • 策略示例:
      • RSI确认: 当出现海龟做多突破信号时,要求RSI也大于50(甚至更高,如60),表明市场处于多头动能;做空突破时,要求RSI小于50(甚至更低,如40)。
    • 优点: 可能过滤掉一些动能不足的弱突破。
    • 缺点: 动量指标有时会与趋势突破产生背离,可能过滤掉有效的早期突破。
  3. 使用波动率指标 (如 Bollinger Bands) 优化入场或识别机会:

    • 目的: 结合布林带的收窄(Squeeze)来寻找潜在的突破机会,或者在突破后利用布林带中轨进行回调入场。
    • 策略示例:
      • Squeeze后突破: 重点关注布林带收窄(低波动)后的海龟突破信号,认为这种突破更可能引发大行情。
      • 回调入场: 在海龟信号触发后(例如突破55日高点),不立即入场,而是等待价格回调至布林带中轨(如20期SMA)附近时再入场,寻求更好的入场价格。
    • 优点: Squeeze可以提示高概率突破时机;回调入场可能改善风险回报比。
    • 缺点: 回调入场可能错过强势的直接突破行情。
  4. 结合成交量 (Volume) 确认突破:

    • 目的: 验证突破是否伴随着资金的积极参与。
    • 策略示例: 海龟突破信号发生时,要求当天的成交量显著高于近期平均成交量(如过去20天的均量)。
    • 优点: 量价结合是经典的技术分析方法,可以增加突破信号的可靠性。
    • 缺点: 成交量数据在某些市场(如外汇现货)不准确或不可用。

结合的注意事项:

  • 复杂性与过拟合: 增加指标会使系统更复杂,更容易产生过拟合历史数据的风险。必须进行严格的样本外测试和前向测试。
  • 保持核心思想: 结合的目的是优化而非颠覆。海龟的核心是捕捉趋势和风险管理,增加的指标不应与其根本冲突。
  • 参数选择: 新增指标的参数与海龟系统自身的参数(突破周期、ATR周期、风险比例等)需要协同优化。

Python 示例:简化版海龟策略 + MA趋势过滤

这个示例将演示一个简化版的海龟系统(使用20日突破入场,10日反向突破出场,不包含完整的加仓和基于N的精确单位计算),并加入一个长期移动平均线(EMA)作为趋势过滤器。

注意: 这仍然是一个教学性质的简化示例,省略了许多实盘细节(如资金管理、滑点、手续费、完整的单位和风险计算)。

import pandas as pd
import numpy as np
import talib # 需要先安装 TA-Lib 库: pip install TA-Lib
import matplotlib.pyplot as plt # 用于可视化

# 1. 准备数据 (使用模拟数据)
dates = pd.date_range(start='2022-01-01', periods=500, freq='D')
# 模拟具有一定趋势性的价格数据
price_noise = np.random.randn(500) * 2
price_trend = np.linspace(0, 30, 500) + np.sin(np.linspace(0, 20, 500)) * 10
close_prices = 100 + price_trend + price_noise
price_data = pd.DataFrame({
    'Close': close_prices,
}, index=dates)
# 基于收盘价生成 OHLC (简化)
price_data['Open'] = price_data['Close'].shift(1).fillna(method='bfill')
price_data['High'] = price_data['Close'] + np.random.rand(500) * 3
price_data['Low'] = price_data['Close'] - np.random.rand(500) * 3
# 确保 High >= Close and Low <= Close
price_data['High'] = price_data[['High', 'Close']].max(axis=1)
price_data['Low'] = price_data[['Low', 'Close']].min(axis=1)

# 2. 计算所需指标
entry_breakout_period = 20 # 入场突破周期 (海龟S1)
exit_breakout_period = 10  # 出场反向突破周期 (海龟S1 Exit)
ma_filter_period = 100     # 移动平均线过滤周期

# 计算唐奇安通道 (Donchian Channel) - 用于判断突破
# talib 没有直接的 Donchian Channel, 我们手动计算 N日高点和低点
price_data['EntryHigh'] = price_data['High'].rolling(entry_breakout_period).max().shift(1) # 前N日的最高价
price_data['EntryLow'] = price_data['Low'].rolling(entry_breakout_period).min().shift(1)  # 前N日的最低价
price_data['ExitHigh'] = price_data['High'].rolling(exit_breakout_period).max().shift(1)  # 前N日的最高价 (用于空头出场)
price_data['ExitLow'] = price_data['Low'].rolling(exit_breakout_period).min().shift(1)   # 前N日的最低价 (用于多头出场)

# 计算移动平均线过滤器
price_data['MA_Filter'] = talib.EMA(price_data['Close'], timeperiod=ma_filter_period)

# (可选) 计算ATR (N) - 虽然本例简化了仓位管理,但可以计算出来看看
# atr_period = 20
# price_data['ATR'] = talib.ATR(price_data['High'], price_data['Low'], price_data['Close'], timeperiod=atr_period)

# 丢弃NaN值
price_data.dropna(inplace=True)

# 3. 生成交易信号 (状态机方式模拟持仓)
price_data['Position'] = 0 # 0: 空仓, 1: 持有多头, -1: 持有空头
position = 0 # 当前持仓状态

for i in range(1, len(price_data)):
    current_close = price_data['Close'].iloc[i]
    ma_filter = price_data['MA_Filter'].iloc[i]
    entry_high = price_data['EntryHigh'].iloc[i]
    entry_low = price_data['EntryLow'].iloc[i]
    exit_high = price_data['ExitHigh'].iloc[i]
    exit_low = price_data['ExitLow'].iloc[i]

    # 当前空仓
    if position == 0:
        # 检查做多信号: 价格突破N日高点 且 价格在MA之上
        if current_close > entry_high and current_close > ma_filter:
            position = 1 # 进入多头
            price_data.loc[price_data.index[i], 'Signal'] = 1 # 标记开仓点
        # 检查做空信号: 价格跌破N日低点 且 价格在MA之下
        elif current_close < entry_low and current_close < ma_filter:
            position = -1 # 进入空头
            price_data.loc[price_data.index[i], 'Signal'] = -1 # 标记开仓点

    # 当前持有多头
    elif position == 1:
        # 检查多头出场信号: 价格跌破退出周期低点
        if current_close < exit_low:
            position = 0 # 平多仓
            price_data.loc[price_data.index[i], 'Signal'] = -2 # 标记平多仓点
        # (如果需要,可以在这里加入止损逻辑,例如 P < EntryPrice - 2*N)

    # 当前持有空头
    elif position == -1:
        # 检查空头出场信号: 价格突破退出周期高点
        if current_close > exit_high:
            position = 0 # 平空仓
            price_data.loc[price_data.index[i], 'Signal'] = 2 # 标记平空仓点
        # (如果需要,可以在这里加入止损逻辑,例如 P > EntryPrice + 2*N)

    price_data['Position'].iloc[i] = position

# 填充信号列的NaN值为0
price_data['Signal'] = price_data['Signal'].fillna(0)


# 4. 可视化
plt.figure(figsize=(16, 10))

# 主图:价格、MA、突破线和信号
ax1 = plt.subplot(2, 1, 1)
ax1.plot(price_data.index, price_data['Close'], label='Close Price', color='black', linewidth=0.8)
ax1.plot(price_data.index, price_data['MA_Filter'], label=f'EMA({ma_filter_period}) Filter', color='orange', linestyle='--', linewidth=1)
ax1.plot(price_data.index, price_data['EntryHigh'], label=f'{entry_breakout_period}-day High', color='red', linestyle=':', linewidth=0.7)
ax1.plot(price_data.index, price_data['EntryLow'], label=f'{entry_breakout_period}-day Low', color='green', linestyle=':', linewidth=0.7)
# ax1.plot(price_data.index, price_data['ExitLow'], label=f'{exit_breakout_period}-day Low (Long Exit)', color='lime', linestyle='-.', linewidth=0.7)
# ax1.plot(price_data.index, price_data['ExitHigh'], label=f'{exit_breakout_period}-day High (Short Exit)', color='magenta', linestyle='-.', linewidth=0.7)

# 标记开仓点
ax1.plot(price_data[price_data['Signal'] == 1].index,
         price_data['Close'][price_data['Signal'] == 1],
         '^', markersize=10, color='lime', label='Enter Long')
ax1.plot(price_data[price_data['Signal'] == -1].index,
         price_data['Close'][price_data['Signal'] == -1],
         'v', markersize=10, color='red', label='Enter Short')
# 标记平仓点 (用不同形状或颜色)
ax1.plot(price_data[price_data['Signal'] == -2].index,
         price_data['Close'][price_data['Signal'] == -2],
         'x', markersize=8, color='blue', label='Exit Long')
ax1.plot(price_data[price_data['Signal'] == 2].index,
         price_data['Close'][price_data['Signal'] == 2],
         'x', markersize=8, color='purple', label='Exit Short')

ax1.set_title('Simplified Turtle Strategy with MA Trend Filter')
ax1.set_ylabel('Price')
ax1.legend(fontsize='small', loc='upper left')
ax1.grid(True)

# 副图:持仓状态
ax2 = plt.subplot(2, 1, 2, sharex=ax1)
ax2.plot(price_data.index, price_data['Position'], label='Position (1=Long, -1=Short, 0=Flat)', color='blue', drawstyle='steps-post')
ax2.set_title('Position Status')
ax2.set_ylabel('Position')
ax2.set_xlabel('Date')
ax2.set_yticks([-1, 0, 1])
ax2.grid(True)

plt.tight_layout()
plt.show()

# 输出最后几行数据看看信号和持仓
print(price_data[['Close', 'EntryHigh', 'EntryLow', 'MA_Filter', 'Signal', 'Position']].tail(20))

代码解释:

  1. 数据准备: 生成模拟OHLC数据,使其包含一些趋势性变化。
  2. 指标计算:
    • 使用 rolling().max().shift(1)rolling().min().shift(1) 计算过去N日的最高价和最低价(即唐奇安通道的上下轨)。.shift(1) 很重要,确保我们用前N日的数据来判断当天是否突破。
    • 使用 talib.EMA 计算长期指数移动平均线作为趋势过滤器。
    • (可选)计算ATR,虽然本例中未用于仓位管理。
  3. 信号生成:
    • 采用一个简单的状态机 (position变量) 来模拟持仓状态(空仓0, 多头1, 空头-1)。
    • 遍历数据,根据当前持仓状态和满足的条件(价格突破、MA过滤、退出信号)来更新持仓状态,并在Signal列中标记交易动作(1:开多, -1:开空, -2:平多, 2:平空)。
    • 关键的过滤逻辑: 只有当价格在MA之上时才考虑做多突破 (current_close > entry_high and current_close > ma_filter);只有当价格在MA之下时才考虑做空突破 (current_close < entry_low and current_close < ma_filter)。
    • 出场逻辑基于简化的S1规则(10日反向突破)。
  4. 可视化:
    • 主图展示价格、MA过滤器、入场突破线,并用不同标记标出开仓和平仓点。
    • 副图展示持仓状态随时间的变化。

总结:

海龟交易法则是量化交易史上的一个里程碑,其核心在于纪律性地跟踪趋势并进行严格的风险管理。虽然原始系统设计为独立运行,但其核心突破逻辑可以与现代技术分析中的其他指标(如MA、ADX、RSI、成交量等)相结合,尝试过滤噪音、适应不同市场环境或优化入场/出场。关键在于理解结合的目的,并通过严格的回测来验证效果,同时警惕增加复杂性可能带来的过拟合风险。Python及其生态(Pandas, TA-Lib, Matplotlib等)为实现、测试和优化这些复杂的CTA策略提供了强大的支持。记住,没有完美的策略,持续的测试、调整和风险控制才是长期成功的关键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值