狂野飙车6鸿蒙版
471.84M · 2025-10-31
平时炒股的时候,你是不是也常有这种感觉: 明明趋势挺猛的,突然就反转了;或者跌得心惊胆战,正想割肉,它却莫名反弹了…
这种“踩不准点”的郁闷,我相信绝大多数散户都经历过。 而量化的本质,其实就是想办法用规则把这种模糊感量化出来。
那么,有没有一种方法,能帮我们大概判断——“当前的上涨/下跌,是不是差不多该到头了?” 答案是:有!这就是我们今天要聊的主角——神奇九转(TD Sequential)。
神奇九转并不是国内股民发明的“土法宝”,它的鼻祖是美国投资大师 Tom DeMark。 Tom DeMark 被称为“华尔街的技术分析奇才”,几十年来专注于研究价格节奏、趋势耗竭的量化方法。 他的 TD Sequential 方法体系,后来被交易员们昵称为“神奇九转十三转”,其中最有名的就是 “九转”(Setup 阶段)。
简单说,它的逻辑就是:
是不是有点意思? 在国内,很多技术派交易者都喜欢用“底部九转”来寻找潜在的抄底信号,用“顶部九转”来预警高位风险。
以底部九转为例(卖出信号同理取反):
比较对象:第 i 根K线与 i-4 根K线的收盘价比较。
Close[i] < Close[i-4],则底部计数 +1;否则计数被打断、重新等待新的起算点。连续性:需要连续满足上面的条件,计数才能从 1 → 9。
起算/重置:
C[i] < C[i-4],底部计数就归零,等待下一次满足时从1重新开始。C[i] > C[i-4]。完美(Perfection,可选):
并行计数:买、卖 Setup 可以并行计算(互不影响)。
边界:由于要和 i-4 比,前4根无法计数;另外若数据小于 30~60 根,信号不稳,尽量用足够长的历史。
上面的内容大家看了可能比较晕,这里用一个具体的例子来说明,加深下大家的理解:
假设我们有一组收盘价序列(按时间顺序):
| 序号 | 收盘价 |
|---|---|
| 1 | 10.0 |
| 2 | 10.2 |
| 3 | 10.5 |
| 4 | 10.3 |
| 5 | 10.1 |
| 6 | 9.9 |
| 7 | 9.7 |
| 8 | 9.6 |
| 9 | 9.5 |
| 10 | 9.4 |
| 11 | 9.2 |
| 12 | 9.0 |
| 13 | 8.9 |
现在我们来算“底部九转”:
? 如果再往下还有一根满足条件,那就是第9次,计数就能到9,形成底部九转完成。
直觉总结:九转寻找的是“与4根前相比持续走弱/走强”的节奏,一旦完成9根,短期趋势可能衰竭,容易出现反向波动(而不是一定反转)。实战里我更倾向把它当作择时辅助而不是单独开仓依据。
接下来我们要实现的功能有:
首先是九转的核心算法,传入包含列: ['open','high','low','close'] 且按时间升序排列的DataFrame,就会返回
td_buy_count : 底部九转计数(0~9)td_sell_count : 顶部九转计数(0~9)td_buy_9 : 是否在该bar触发底部9td_sell_9 : 是否在该bar触发顶部9td_buy_perfect9 : 是否买setup完美9td_sell_perfect9 : 是否卖setup完美9def compute_td_setup(df: pd.DataFrame):
df = df.copy()
n = len(df)
buy_count = np.zeros(n, dtype=int)
sell_count = np.zeros(n, dtype=int)
td_buy_9 = np.zeros(n, dtype=bool)
td_sell_9 = np.zeros(n, dtype=bool)
td_buy_perfect9 = np.zeros(n, dtype=bool)
td_sell_perfect9 = np.zeros(n, dtype=bool)
close = df['close'].values
high = df['high'].values
low = df['low'].values
for i in range(n):
# 需要与 i-4 比较
if i >= 4:
# 底部九转:收盘 < 4根前收盘
if close[i] < close[i-4]:
buy_count[i] = buy_count[i-1] + 1 if i > 0 else 1
else:
buy_count[i] = 0
# 顶部九转:收盘 > 4根前收盘
if close[i] > close[i-4]:
sell_count[i] = sell_count[i-1] + 1 if i > 0 else 1
else:
sell_count[i] = 0
else:
buy_count[i] = 0
sell_count[i] = 0
# 标记到9
if buy_count[i] == 9:
td_buy_9[i] = True
# 完美9(可选规则):第8或第9根的最低价 < min(第6, 第7根的最低价)
# 注意索引换算:当前i是第9,i-1是第8;i-3第6,i-2第7
if i >= 7: # 至少要有第6、7、8根
cond = (low[i-1] < min(low[i-3], low[i-2])) or (low[i] < min(low[i-3], low[i-2]))
td_buy_perfect9[i] = bool(cond)
if sell_count[i] == 9:
td_sell_9[i] = True
# 卖setup完美9:第8或第9根的最高价 > max(第6, 第7根的最高价)
if i >= 7:
cond = (high[i-1] > max(high[i-3], high[i-2])) or (high[i] > max(high[i-3], high[i-2]))
td_sell_perfect9[i] = bool(cond)
df['td_buy_count'] = buy_count
df['td_sell_count'] = sell_count
df['td_buy_9'] = td_buy_9
df['td_sell_9'] = td_sell_9
df['td_buy_perfect9'] = td_buy_perfect9
df['td_sell_perfect9'] = td_sell_perfect9
return df
接下来是绘图功能
def plot_kline_with_td_counts(df, title=""):
"""
在K线上标注 td_buy_count / td_sell_count
"""
df = df.copy()
# 自定义红涨绿跌的颜色风格
my_style = mpf.make_mpf_style(
base_mpf_style='charles', # 继承基础风格
marketcolors=mpf.make_marketcolors(
up='red', # 涨:红色
down='green', # 跌:绿色
edge='inherit', # K线边框颜色(inherit 表示继承 up/down 颜色)
wick='inherit', # 上下影线颜色
volume='inherit' # 成交量颜色
),
rc={'font.family': 'SimHei'}
)
# mplfinance 绘图并返回 fig 和 axes
fig, axes = mpf.plot(
df, type='candle', mav=(5,10,20), volume=True,
style=my_style, title=title, figratio=(16,9), figscale=1.1,
tight_layout=True, returnfig=True
)
ax = axes[0] # 主图
# 用整数索引代替 x 轴
x_vals = np.arange(len(df))
for i, row in enumerate(df.itertuples()):
if row.td_buy_count > 0:
ax.text(
x_vals[i], row.low*0.995, str(int(row.td_buy_count)),
ha='center', va='top', fontsize=8, color='green'
)
if row.td_sell_count > 0:
ax.text(
x_vals[i], row.high*1.005, str(int(row.td_sell_count)),
ha='center', va='bottom', fontsize=8, color='red'
)
plt.show()
接下来我们通过xtdata.get_stock_list_in_sector('沪深A股')获取全部股票列表,通过一个循环就可以查找出谁目前处于九转的位置了。
收盘 <= 前两根最低 的 bar(买方向),形成 TD Sequential 的“倒计时”部分,用于捕捉更完全的耗竭信号。