☰
Vibe-Trading 缠论分型(FX)识别完全指南:去包含、顶底分型与笔端点实战解析
2026/10/17 18:32:30 网站建设 项目流程

Vibe-Trading 缠论分型(FX)识别完全指南:去包含、顶底分型与笔端点实战解析

【免费下载链接】Vibe-Trading"Vibe-Trading: Your Personal Trading Agent"项目地址: https://gitcode.com/GitHub_Trending/vi/Vibe-Trading

本文是 Vibe-Trading 项目中agent/src/skills/chanlun缠论技能包的核心概念系列之一。缠论(缠中说禅)是一套完全基于价格结构的形态分析方法,而分型(FX)是整个体系最底层的识别单元——去包含处理、顶底分型判定、笔端点确认,直至中枢构建与买卖点判定,全部建立在分型之上。读完本文,你将掌握分型的数学定义与条件、去包含合并规则、czsc中FX数据结构的字段语义,并能结合仓库中的example_signal_engine.py信号引擎,把分型识别直接用于 A 股、加密货币、期货等多市场 OHLCV 数据的实时分析与信号生成。

一、分型在缠论体系中的定位

缠论的核心链路是:

原始K线 → 去包含处理 → 分型识别 → 笔检测 → 中枢构建 → 买卖点判定

分型位于整条链路的第三环,是连接原始价格数据与高层次结构(笔、中枢、买卖点)的必经桥梁。在 SKILL.md 中,分型被定义为整个体系的"最基础识别单元":

分型(FX):顶分型:中间K线最高;底分型:中间K线最低

  • 没有分型,就无法定义笔(笔的两端必须是顶/底分型);
  • 没有笔,就无法构建中枢(中枢由至少 3 笔构成);
  • 没有中枢,一买/二买/三买等买卖点信号就无从谈起。

因此,分型识别的正确性直接决定了下游所有缠论信号的质量。

二、分型的定义:连续三根去包含后的 K 线

分型由连续三根去包含后的 K 线构成。这里有两个关键词需要精确理解:

  1. "去包含后":分型不是直接作用于原始 K 线,而是作用于经过"包含关系处理"之后的 K 线序列。包含关系会破坏分型的几何形态,必须先合并。
  2. "连续三根":分型是局部三根 K 线的形态判定,属于缠论中最小的局部结构。

顶分型(Mark.G):

██ ██ ██ ██ ██

底分型(Mark.D):

██ ██ ██ ██ ██

三、去包含处理:分型识别的前置步骤

3.1 包含关系的判定

当相邻两根 K 线存在价格区间完全覆盖时,即一根 K 线的高低点完全落在另一根的范围内(k1.high >= k2.high 且 k1.low <= k2.low,或反之),两者即为包含关系:

  • 一根 K 线的最高价被另一根覆盖,且其最低价也被另一根覆盖。

3.2 合并规则

去包含处理的方向由前一根非包含 K 线的方向决定(上升或下降):

方向合并取法含义
上升方向取两根 K 线中较大的高点和较大的低点突出强势,向上延伸
下降方向取较小的高点和较小的低点突出弱势,向下延伸

用公式表达(以两根 K 线 k1、k2 合并为 k' 为例):

  • 上升方向:k'.high = max(k1.high, k2.high),k'.low = max(k1.low, k2.low)
  • 下降方向:k'.high = min(k1.high, k2.high),k'.low = min(k1.low, k2.low)

从源码结构看,czsc 库内部正是以"去包含后的新 K 线(NewBar)"序列作为分型与笔的输入,这也解释了为什么FX.elements字段的类型是List[NewBar](详见下文第四节)。

3.3 为什么必须去包含

如果两根 K 线存在包含关系,它们实际上传达的是同一个方向的延伸信息,而非独立的价格行为。不去包含会导致:

  • 本应构成分型的"中间高两边低"形态被包含 K 线破坏;
  • 分型数量虚增或漏判,笔的端点错位;
  • 下游中枢区间、买卖点信号全部失真。

四、顶分型与底分型的精确条件

设构成分型的三根去包含 K 线从左到右为k1, k2, k3。

4.1 顶分型(Mark.G)

条件:

k1.high < k2.high > k3.high 且 k1.low < k2.low > k3.low

即:中间 K 线 k2 的最高价是三者中的最高,同时 k2 的最低价也是三者中的最高。

含义:价格在 k2 处冲到局部高点,随后 k3 的高点与低点均回落——上涨力量衰竭,可能转跌。顶分型是一卖、二卖、三卖等卖出信号确认的形态前提。

4.2 底分型(Mark.D)

条件:

k1.high > k2.high < k3.high 且 k1.low > k2.low < k3.low

即:中间 K 线 k2 的最高价是三者中的最低,同时 k2 的最低价也是三者中的最低。

含义:价格在 k2 处探到局部低点,随后 k3 的高点与低点均回升——下跌力量衰竭,可能转涨。底分型是一买、二买、三买等买入信号确认的形态前提。

4.3 关键要点

  • 顶分型与底分型判定同时要求 high 和 low 两个维度成立,单一维度不构成分型;
  • 分型是必要条件而非充分条件:出现分型只代表"转折的可能",是否真正形成笔,还需满足笔的构成条件(顶底交替、无包含、最小 K 线数等,见 笔.md)。

五、czsc 中的 FX 数据结构

分型在czsc库中以FXdataclass 表示,字段语义如下:

@dataclass class FX: symbol: str # 标的代码 dt: datetime # 分型时间(取中间K线时间) mark: Mark # Mark.G(顶)/ Mark.D(底) high: float # 分型最高价 low: float # 分型最低价 fx: float # 分型值(顶取high,底取low) elements: List[NewBar] # 构成分型的三根去包含K线
字段类型语义与来源
symbolstr标的代码,透传自输入 K 线的symbol
dtdatetime分型时间,取中间 K 线(k2)的时间,代表转折发生的时点
markMark分型类型枚举:Mark.G(顶)/Mark.D(底)
highfloat分型最高价,即三根 K 线的最高价
lowfloat分型最低价,即三根 K 线的最低价
fxfloat分型值:顶分型取 high,底分型取 low。这是笔端点比较时的关键数值
elementsList[NewBar]构成该分型的三根去包含后的 K 线,印证了分型必须建立在去包含序列之上

其中fx字段的设计值得注意:顶分型用high、底分型用low,这使得在笔的判定中可以通过统一的"分型值"比较大小(例如上升笔要求fx_b.fx > fx_a.fx,详见 笔.md),从而避免在不同类型分型间做差异化的取价逻辑。

六、使用示例:从分型到笔端点

分型最常见的消费方式,是作为笔(BI)的端点。笔连接相邻的顶分型与底分型,因此遍历CZSC分析器输出的笔列表,即可获得每一笔的起点与终点分型:

from czsc import CZSC c = CZSC(bars) # 笔的端点就是分型 for bi in c.bi_list: print(f"起点分型: {bi.fx_a.mark.value} {bi.fx_a.dt}") print(f"终点分型: {bi.fx_b.mark.value} {bi.fx_b.dt}")

其中:

  • bi.fx_a为该笔的起点分型(FX对象);
  • bi.fx_b为该笔的终点分型(FX对象);
  • 上升笔满足fx_a.mark = Mark.D、fx_b.mark = Mark.G;下降笔则相反;
  • mark.value输出分型类型的字符串值(如"G"/"D")。

6.1 组合形态输出示例

结合 笔.md 的示例,可以更直观地观察分型时间与价格在笔中的体现:

from czsc import CZSC c = CZSC(bars) for bi in c.bi_list[-5:]: d = "↑" if bi.direction.value == "Up" else "↓" print(f"{d} {bi.fx_a.dt:%m-%d} -> {bi.fx_b.dt:%m-%d} " f"H={bi.high:.0f} L={bi.low:.0f} len={bi.length}")

这里fx_a.dt与fx_b.dt正是分型的时间字段(取中间 K 线时间),反映了转折时点的精确刻度。

七、仓库集成:分型在信号引擎中的实战落地

分型本身是形态识别单元,但真正的实战价值体现在它如何驱动交易信号。仓库中的 example_signal_engine.py 演示了完整的落地链路。

7.1 引擎整体链路

OHLCV DataFrame → _df_to_bars → RawBar列表 → CZSC(bars[:30], get_signals=...) → 逐根 c.update(bar) 增量更新 → _evaluate_signals → 1(做多)/-1(做空)/0(观望)

其中CZSC在内部完成去包含 → 分型 → 笔 → 中枢的自动构建,分型识别对用户完全透明,但信号判定逻辑需要显式引用分型的下游产物(笔与中枢)。

7.2 分型派生信号在引擎中的判定逻辑

_evaluate_signals方法展示了分型识别结果如何被逐级消费:

# 一买/一卖信号(背驰点 + 分型确认) buy1_key = [k for k in signals if "BUY1" in k] if buy1_key and "一买" in str(signals.get(buy1_key[0], "")): return 1 # 三笔形态:向上盘背做多 / 向下盘背做空 three_bi_key = [k for k in signals if "三笔" in k] if three_bi_key: val = str(signals.get(three_bi_key[0], "")) if "向上盘背" in val: return 1 if "向下盘背" in val: return -1 # 笔基础信号 + 中枢位置辅助 bi_key = [k for k in signals if "V230228" in k] if bi_key and len(c.bi_list) >= 3: val = str(signals.get(bi_key[0], "")) zs = _check_zhongshu(c.bi_list) if zs and zs.is_valid: last_close = c.bars_raw[-1].close if "向下_转折" in val and last_close <= zs.zd: return 1 if "向上_转折" in val and last_close >= zs.zg: return -1

信号约定(与 SKILL.md 一致):

信号含义引擎输出
1做多一买、三笔向上盘背、五笔类一买、中枢下沿附近向下转折
-1做空一卖、三笔向下盘背、五笔类一卖、中枢上沿附近向上转折
0观望其余情况

注意:这里的"一买/一卖"信号需要底/顶分型作为最终确认条件(见 一买一卖.md),而中枢位置辅助判断依赖的是c.bi_list——笔的端点即分型,因此分型识别质量是这一切的根基。

7.3 完整可运行示例:BTC-USDT 日线信号

example_signal_engine.py的__main__部分给出了一个端到端示例,拉取 OKX 的 BTC-USDT 日线数据并运行信号引擎:

import requests import pandas as pd from czsc import Freq BASE_URL = "https://www.okx.com/api/v5" # 获取 BTC 日线数据 resp = requests.get(f"{BASE_URL}/market/candles", params={ "instId": "BTC-USDT", "bar": "1D", "limit": "300" }) candles = resp.json()["data"] # 转为 DataFrame(注意接口返回倒序,需 reversed) columns = ["ts", "open", "high", "low", "close", "vol", "volCcy", "volCcyQuote", "confirm"] df = pd.DataFrame(reversed(candles), columns=columns) df["ts"] = pd.to_datetime(df["ts"].astype("int64"), unit="ms") df = df.set_index("ts") for col in ["open", "high", "low", "close"]: df[col] = df[col].astype(float) df["volume"] = df["vol"].astype(float) df["amount"] = df["volCcy"].astype(float) # 运行信号引擎 engine = SignalEngine(freq=Freq.D) signals = engine.generate({"BTC-USDT": df}) # 输出结果 sig = signals["BTC-USDT"] buys = sig[sig == 1] sells = sig[sig == -1] print(f"BTC-USDT 缠论信号 ({len(df)} 根K线)") print(f" 做多信号: {len(buys)} 个") print(f" 做空信号: {len(sells)} 个") if len(buys) > 0: print(f" 最近做多: {buys.index[-1]:%Y-%m-%d}") if len(sells) > 0: print(f" 最近做空: {sells.index[-1]:%Y-%m-%d}")

7.4 从 DataFrame 构造 RawBar

引擎的数据入口是_df_to_bars,它将任意 OHLCV DataFrame 规范化为czsc的RawBar列表,这也是分型识别的输入格式:

def _df_to_bars(df: pd.DataFrame, symbol: str, freq: Freq = Freq.D) -> list: bars = [] for i, (dt, row) in enumerate(df.iterrows()): if not isinstance(dt, datetime): dt = pd.Timestamp(dt).to_pydatetime() bars.append(RawBar( symbol=symbol, id=i, dt=dt, freq=freq, open=float(row["open"]), close=float(row["close"]), high=float(row["high"]), low=float(row["low"]), vol=float(row.get("volume", row.get("vol", 0))), amount=float(row.get("amount", 0)), )) return bars

RawBar的完整字段约定(引自 SKILL.md):

字段类型说明
symbolstr标的代码
idint序号(从 0 开始)
dtdatetime时间
freqFreq频率:Freq.F1/F5/F15/F30/F60/D/W/M
openfloat开盘价
closefloat收盘价
highfloat最高价
lowfloat最低价
volfloat成交量
amountfloat成交额

7.5 引擎的增量更新机制

generate方法展示了分型/笔的增量计算模式:

if len(bars) < 30: result[code] = signal continue # 先用前 30 根K线初始化分析器,再逐根增量更新 c = CZSC(bars[:30], get_signals=_get_signals) for bar in bars[30:]: c.update(bar) sig = self._evaluate_signals(c) if sig != 0: signal.iloc[bar.id] = sig

这种"初始批次 + 逐根c.update(bar)"的模式,充分利用了 czsc 的增量更新能力(SKILL.md 明确说明 czsc "支持增量更新,适合实时分析")。这意味着分型识别不是每次全量重算,而是新 K 线到达时局部刷新,适合实盘流式行情场景。同时少于 30 根 K 线的标的会被跳过,保证了分型、笔识别有足够的预热数据。

7.6 信号函数的选择

引擎选用的缠论信号函数(来自czsc.signals.cxt):

from czsc.signals.cxt import ( cxt_first_buy_V221126, cxt_first_sell_V221126, cxt_bi_base_V230228, cxt_three_bi_V230619, cxt_five_bi_V230619, )

在 SKILL.md 中,czsc 共内置 43 个缠论信号函数,核心分类如下:

函数说明类型
cxt_first_buy_V221126一买信号买卖点
cxt_first_sell_V221126一卖信号买卖点
cxt_second_bs_V230320均线辅助二买二卖买卖点
cxt_third_bs_V230318均线辅助三买三卖买卖点
cxt_third_buy_V230228笔三买辅助买卖点
cxt_double_zs_V230311两中枢组合判断 BS1中枢
cxt_three_bi_V230618三笔形态分类形态
cxt_five_bi_V230619五笔形态分类形态
cxt_seven_bi_V230620七笔形态分类形态
cxt_nine_bi_V230621九笔形态分类形态
cxt_eleven_bi_V230622十一笔形态分类形态
cxt_bi_base_V230228BI 基础信号(方向/转折)基础
cxt_bi_end_V230312MACD 辅助笔结束辅助
cxt_range_oscillation_V230620区间震荡判断辅助
cxt_zhong_shu_gong_zhen_V221221大小级别中枢共振中枢

其中一买/一卖信号函数还以di=1参数显式指定"倒数第 1 笔"作为判定基准(见 一买一卖.md),信号输出格式为{freq}_D{di}B_BUY1/{freq}_D{di}B_SELL1。

八、分型与其他核心概念的衔接

理解分型,必须同时理解它在缠论体系中的上下游关系:

概念与分型的关系详细文档
分型(FX)本文主题:三根去包含 K 线的形态单元分型.md
笔(BI)笔的端点就是分型(顶底交替、无包含、最小 7 根去包含 K 线)笔.md
中枢(ZS)至少 3 笔构成的价格重叠区域,分型→笔→中枢的第三层中枢.md
一买/一卖背驰 + 分型确认的趋势反转信号一买一卖.md
二买/二卖一买/一卖后回调不破底/顶的确认信号二买二卖.md
三买/三卖中枢上移/下移后回调不进入前中枢的信号三买三卖.md

从仓库结构看,chanlun技能还被用于多智能体协同场景:在 technical_analysis_panel.yaml 中,wave_analyst(波浪分析师)智能体被配置为同时加载elliott-wave与chanlun两个技能(skills: [elliott-wave, chanlun]),并将缠论的分型/笔/中枢结构作为艾略特波浪计数的交叉验证("Fractal strokes strict, Segments and central pivot ranges")。这表明分型识别不仅是单标的的技术指标,还能为多分析师团队的形态共振判断提供独立证据链。

九、实战注意事项与常见误区

  1. 分型必须基于去包含序列:直接对原始 K 线找"三根形态"会得到大量假分型,务必确认数据已通过 czsc 的包含处理。
  2. 分型不等于转折确认:顶分型出现后价格可能继续创新高(分型失败),实盘建议结合 MACD 背驰(cxt_bi_end_V230312)或中枢位置辅助过滤。
  3. 数据预热要求:信号引擎要求至少 30 根 K 线(len(bars) < 30直接跳过),更精细的买卖点判定需要更长的笔序列(如 一买一卖.md 要求至少两个向下/向上中枢)。
  4. 频率选择:Freq.D(日线)适合趋势级分析;Freq.F30/F60适合日内;分型数量会随周期缩短而增多,注意噪声放大。
  5. 安装依赖:运行前需安装czsc(v0.9.68+,纯 Python 实现,可选 Rust 加速后端):
pip install czsc requests pandas
  1. 适用范围:分型识别只依赖 OHLCV 数据,因此适用于任何有 K 线数据的市场(A 股、加密货币、期货等),无需额外的基本面或新闻输入。

十、小结

分型是缠论最基础的识别单元:三根去包含后的 K 线,通过中间 K 线的高点/低点同时最高(顶分型)或同时最低(底分型)来判定局部力量衰竭。它的上游是去包含处理(上升取大、下降取小),下游则是笔、中枢与整个买卖点体系。在 Vibe-Trading 中,分型识别通过czsc的FX数据结构与CZSC分析器自动完成,并经由 example_signal_engine.py 的SignalEngine将分型派生的笔与中枢信号转化为1/-1/0的可执行交易信号,同时支持增量更新以适配实时行情。掌握分型的判定逻辑与数据结构,是理解并调优整套缠论信号引擎的第一步。

【免费下载链接】Vibe-Trading"Vibe-Trading: Your Personal Trading Agent"项目地址: https://gitcode.com/GitHub_Trending/vi/Vibe-Trading

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询