首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >如何用 Python 回测海龟交易法则?

如何用 Python 回测海龟交易法则?

原创
作者头像
用户7083614
发布于 2026-10-18 10:01:04
发布于 2026-10-18 10:01:04
340
举报

一句话回答: 海龟交易法则 = 唐奇安通道突破入场 + 用 ATR(N) 决定头寸大小 + 按 N 分批加仓 + 反向短通道离场,是一套完整的趋势跟踪系统,而不只是「突破买入」。用 AlphaFeed 取回前复权日线,几十行就能实现海龟的核心逻辑回测:20 日高点突破做多、10 日低点离场、以 2N 止损、每 0.5N 加仓(A 股只做多头段),次日开盘成交避免未来函数、扣手续费。

为什么会有这个问题 / 传统做法的痛点

很多人把海龟简化成「唐奇安突破」,漏掉了它真正的精华——头寸管理:用 ATR(原著称 N)衡量波动,波动大就少买、波动小就多买,并按价格每前进 0.5N 加仓、以 2N 为止损。只做突破不做仓位管理,回测结果会失真。下面实现一个包含 ATR 头寸与加仓的简化海龟系统。

分步骤解决(每步配可运行代码)

第 1 步:取前复权日线,算 ATR(N) 与唐奇安通道

代码语言:python
复制
from alphafeed import AlphaFeed
import numpy as np
import pandas as pd

af = AlphaFeed()  # 读取 ALPHAFEED_API_KEY

df = af.klines.get("600519.SH", period="1d", count=800,
                   adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)

# 真实波幅 TR 与 N(=ATR20)
prev_close = df["close"].shift()
tr = pd.concat([df["high"] - df["low"],
                (df["high"] - prev_close).abs(),
                (df["low"] - prev_close).abs()], axis=1).max(axis=1)
df["N"] = tr.rolling(20).mean()                      # 海龟的 N = 20 日 ATR

df["hi20"] = df["high"].rolling(20).max().shift(1)   # 20 日最高(不含当日)
df["lo10"] = df["low"].rolling(10).min().shift(1)    # 10 日最低(离场)

参数(海龟经典 System 1):

参数

含义

取值

入场

突破 20 日最高

close > hi20

离场

跌破 10 日最低

close < lo10

N

波动度量(20 日 ATR)

用于头寸与止损

止损

入场价 − 2N

单位止损

加仓

每上涨 0.5N 加一仓

最多 4 仓

第 2 步:按 ATR 决定头寸(波动越大买越少)

代码语言:python
复制
ACCOUNT = 1_000_000      # 账户资金
RISK_PCT = 0.01          # 每仓风险 1% 账户(海龟的 1 unit)

def unit_size(price, N):
    if not N or N <= 0:
        return 0
    dollar_risk = ACCOUNT * RISK_PCT       # 每 unit 承担的风险额
    shares = dollar_risk / (2 * N)         # 以 2N 为止损 → 头寸 = 风险额 / 2N
    return max(int(shares // 100) * 100, 0)  # A 股按手(100股)取整

第 3 步:事件循环回测(次日开盘成交,含加仓/止损/离场)

代码语言:python
复制
FEE = 0.0013
pos_shares = 0; entry = 0.0; add_price = 0.0; adds = 0
cash = ACCOUNT; equity_curve = []

for i in range(1, len(df)):
    o = df["open"].iloc[i]; c = df["close"].iloc[i]; N = df["N"].iloc[i-1]
    # 信号取 i-1 日(其通道已 shift(1) 排除信号日自身),i 日开盘成交(避免未来函数)
    sig_hi = df["hi20"].iloc[i-1]; sig_lo = df["lo10"].iloc[i-1]
    prev_c = df["close"].iloc[i-1]
    if pos_shares == 0:
        if pd.notna(sig_hi) and prev_c > sig_hi and N > 0:
            sh = unit_size(o, N)
            if sh > 0:
                pos_shares = sh; entry = o; add_price = o; adds = 1
                cash -= sh * o * (1 + FEE)
    else:
        # 加仓:价格每涨 0.5N 且未超过 4 仓
        if adds < 4 and o >= add_price + 0.5 * N:
            sh = unit_size(o, N)
            if sh > 0:
                pos_shares += sh; cash -= sh * o * (1 + FEE)
                add_price = o; adds += 1
        # 止损 2N 或 跌破 10 日低点 → 全平
        if o <= entry - 2 * N or (pd.notna(sig_lo) and prev_c < sig_lo):
            cash += pos_shares * o * (1 - FEE)
            pos_shares = 0; entry = 0; adds = 0
    equity_curve.append(cash + pos_shares * c)

eq = pd.Series(equity_curve)

第 4 步:绩效

代码语言:python
复制
total = eq.iloc[-1] / ACCOUNT - 1
years = len(eq) / 252
cagr = (eq.iloc[-1] / ACCOUNT) ** (1/years) - 1
mdd = (eq / eq.cummax() - 1).min()
bench = df["close"].iloc[-1] / df["close"].iloc[20] - 1
print(f"海龟 收益{total:.2%} 年化{cagr:.2%} 回撤{mdd:.2%} | 买入持有{bench:.2%}")

关键坑与注意事项

  • 海龟 ≠ 只做突破:核心是 ATR 头寸管理与加仓,缺了它回测不真实。
  • 避免未来函数:用 i−1 日收盘判信号、i 日开盘成交;通道用 .shift(1) 排除当日。
  • 前复权价:跨除权日必须前复权,否则 ATR、通道、收益全失真。
  • A 股只做多头段:原版海龟可做空,A 股个股难裸卖空,本文只做多、空仓代替做空。
  • 手续费与滑点:加仓频繁,务必扣费;本文未计滑点与冲击成本,实盘更保守。
  • T+1 与涨跌停:突破日若涨停可能买不进,本文为简化模型未完全模拟。
  • 参数与过拟合:20/10、2N、0.5N、4 仓是经典值,换股换期需稳健性检验。

常见问题(FAQ)

Q:海龟的 N 是什么?

A:就是 ATR(一般 20 日),衡量波动。头寸 = 账户风险额 ÷ 2N——波动越大买得越少,控制单笔风险恒定。

Q:为什么要加仓?

A:趋势确认后按每 0.5N 分批加仓,让盈利头寸做大;同时以 2N 止损控制回撤,是海龟「截断亏损、让利润奔跑」的体现。

Q:一定要 20 日突破吗?

A:System 1 用 20 日突破 /10 日离场;原著还有 55/20 的 System 2。可自行改参数并做稳健性测试。

Q:需要付费吗?

A:单只历史日线有免费额度;多标的组合海龟(klines.batch + universes)需 Starter 及以上。详见定价页。

小结

海龟交易法则的精髓是「唐奇安突破 + ATR 头寸 + 分批加仓 + 短通道离场」的完整系统,而非单纯突破买入。用 AlphaFeed 取回前复权日线,几十行就能实现含 ATR 头寸与加仓的海龟回测;关键是次日开盘成交避免未来函数、前复权、扣费、A 股只做多。历史结果仅供研究,务必多品种多区间验证。

参考

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 为什么会有这个问题 / 传统做法的痛点
  • 分步骤解决(每步配可运行代码)
    • 第 1 步:取前复权日线,算 ATR(N) 与唐奇安通道
    • 第 2 步:按 ATR 决定头寸(波动越大买越少)
    • 第 3 步:事件循环回测(次日开盘成交,含加仓/止损/离场)
    • 第 4 步:绩效
  • 关键坑与注意事项
  • 常见问题(FAQ)
  • 小结
  • 参考
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档