算法规格书 · ema_triple_v1

M1 TrendModule 趋势判断算法 · EMA 三线多头/空头排列法 · 2026-05-16

algorithm_layer M1 TrendModule framework v1 精确可实现
§1
身份声明
本规格书在三层文档体系中的位置
属性值
algorithm_idema_triple_v1
所属模块M1 TrendModule
框架层引用字段M0.trend_method_main = "ema_triple_v1"
文档层级算法层(夹在框架层与实例层之间)
触发时机每根已完结 K 线收盘后,由运行时调用一次
有状态是(维护 trend_state 跨 K 线持续)
§2
接口映射
本算法对框架 M1 输出字段的填充方式
框架字段本算法填充方式为空时
directionEMA 三线大小关系推导,见 §4.A不会为空
stage由 segment_count 映射,见 §4.Fdirection=震荡时 null
trend_origin_price当前趋势起点收盘价,见 §4.Cdirection=震荡时 null
extreme_price当前趋势最极值收盘价,见 §4.Ddirection=震荡时 null
pullback_depth公式见 §4.E分母≤0 或震荡时 null
metadata.segment_count段数状态机计数,见 §4.Edirection=震荡时 null
source_close_time触发本次计算的 K 线收盘 ISO 时间不会为空
§3
私有参数
从 M0 读取;实例层在 metadata 中覆盖
参数类型默认值说明
ema_fastint21快线周期,三步曲标准值
ema_midint55中线周期
ema_slowint144慢线周期
kline_windowintM0.kline_windowEMA 计算回看 K 线根数;同时限定状态变量搜索窗口
price_fieldstr"close"EMA 计算所用价格字段;决策①:统一用收盘价,不用高低点影线
§4
算法步骤
每次 K 线收盘后按 A→F 顺序执行
A · 方向判断(direction)
1
取最新已完结 K 线收盘价序列(共 kline_window 根),计算 EMA_fast、EMA_mid、EMA_slow。
2
EMA 计算公式:k = 2/(n+1),EMA[0] = close[0],EMA[i] = close[i]×k + EMA[i-1]×(1-k)。取序列最后一项(最新 K 线)对应值。
3
方向判定:
  • EMA_fast > EMA_mid > EMA_slow → direction = 涨势
  • EMA_fast < EMA_mid < EMA_slow → direction = 跌势
  • 其他(缠绕 / 交叉 / 任意两线相等)→ direction = 震荡(框架短路,步骤 B-F 跳过)
A 方向变化触发重置
R
当 direction 与上一根 K 线的 direction 不同且新 direction ≠ 震荡 时,触发状态重置:
  • trend_origin_price、extreme_price、segment_count、segment_state 全部清空,按步骤 B-F 重新初始化。
  • 决策②:上一根为震荡、本根方向恢复非震荡时,同样触发重置(震荡视为趋势断裂,不延续旧段数)。
B · 内部状态变量(跨 K 线持久化)
变量名类型初始值说明
current_directionstr—上一根 K 线的 direction,用于检测变化
trend_origin_pricefloat—当前趋势起点价格
extreme_pricefloat—当前趋势极值价格
segment_countint1当前趋势段数
segment_statestr"extending"段计数状态机当前状态:extending / pullback
prev_extremefloat—进入 pullback 前的 extreme_price 快照,用于判断是否突破
C · 趋势起点价格(trend_origin_price)
1
仅在步骤 A 触发状态重置时更新(即趋势方向切换的第一根 K 线)。
2
涨势起点:在当前 K 线往前回溯 kline_window 根内,找到最近一根收盘价低于 EMA_slow 的 K 线,取其收盘价。
若回溯窗口内所有 K 线均在 EMA_slow 之上,则取窗口内最低收盘价。
含义:这根 K 线是均线形成多头排列之前的最低价点,代表本轮涨势"从哪里出发"。
3
跌势起点:对称定义——最近一根收盘价高于 EMA_slow 的 K 线收盘价;若均在 EMA_slow 之下则取窗口内最高收盘价。
4
趋势持续期间,trend_origin_price 不随行情变化更新,只在方向切换时重新计算。
D · 极值价格(extreme_price)
1
初始化(重置时):extreme_price = close[当前 K 线]。
2
每根 K 线收盘后更新:
  • 涨势:extreme_price = max(extreme_price, close[当前])
  • 跌势:extreme_price = min(extreme_price, close[当前])
3
决策③:使用收盘价而非 K 线影线高低点。收盘价更稳定,避免单根大影线造成误判。
E · 段数计数(segment_count)状态机
状态:extending(趋势延伸中)
初始进入条件:趋势方向确认(重置或首次确认)
涨势:close[当前] ≤ EMA_fast[当前] → 进入 pullback;记录 prev_extreme = extreme_price
跌势:close[当前] ≥ EMA_fast[当前] → 进入 pullback;记录 prev_extreme = extreme_price
状态:pullback(回调中)
涨势:close[当前] > prev_extreme → segment_count += 1;extreme_price = close[当前];回到 extending
跌势:close[当前] < prev_extreme → segment_count += 1;extreme_price = close[当前];回到 extending
注:pullback 期间若未突破 prev_extreme,继续保持 pullback 状态,不增加 segment_count;extreme_price 仍按步骤 D 规则更新。
!
决策④:pullback 的判定边界是 EMA_fast(快线)而非 EMA_mid。含义:价格回到快线即算开始回调,回调后只要突破前极值即计新段,不要求回到 EMA_mid。这与三步曲"快线是顺势入场的参考"一致。
F · 回调深度(pullback_depth)
// 涨势
pullback_depth = (extreme_price − close[当前]) ÷ (extreme_price − trend_origin_price)
// 跌势
pullback_depth = (close[当前] − extreme_price) ÷ (trend_origin_price − extreme_price)
// 边界处理
if 分母 ≤ 0 → pullback_depth = null // origin 与 extreme 重合,趋势刚启动 if pullback_depth < 0 → pullback_depth = 0 // 价格在 extreme 另一侧(未回调) if pullback_depth > 1 → pullback_depth = 1 // 价格越过 origin(回调超 100%)
!
决策⑤:close[当前] 使用当前已完结 K 线的收盘价,不是实时价(盘中不计算)。与 EMA 计算所用价格字段一致(均为 close)。
F · 阶段映射(stage)
segment_countstage含义
1初期趋势第一段,力量最强,可积极入场
2中期第二段,仍可入场但需更严格理由
≥ 3末期第三段及以后,趋势衰竭风险上升,信号评分惩罚 −3
§5
设计决策汇总
算法规格中不从框架文档继承的主观选择,需用户确认或覆盖
决策①
价格字段 = 收盘价(不用影线)
EMA、extreme_price、pullback_depth 均基于 close,避免单根长影线干扰判断。若要使用 high/low,需在实例层覆盖 metadata.price_field = "high"。
决策②
震荡后恢复方向视为新趋势,重置所有状态
更保守,避免继承震荡前的旧段数带来误判。替代方案:保留状态(更激进),取决于用户偏好。
决策③
extreme_price 用收盘价,不用 K 线影线高低
与决策① 一致,使 pullback_depth 稳定。若用影线,单根大顶/底影线会使 extreme 跳变,造成 pullback_depth 虚高。
决策④
segment 回调判定边界 = EMA_fast(EMA21)
价格 close ≤ EMA21(涨势)即算进入回调阶段。替代方案:close ≤ EMA_mid(更宽),适合慢节奏品种。
决策⑤
pullback_depth 的 current_price = 当前完结 K 线收盘价
不使用实时价(盘中价)。盘中每 tick 都会造成 depth 波动,不适合作为稳定的策略输入。
§6
边界条件与特殊处理
实现时必须覆盖的异常场景
1
K 线不足:若历史 K 线数 < ema_slow(144),EMA_slow 不可信,强制 direction = 震荡,所有输出 null。
2
趋势极短即反转:若方向切换时 trend_origin_price 搜索范围内找不到满足条件的 K 线,fallback 取当前 K 线收盘价作为 origin。
3
极值与起点重合(趋势刚启动第一根 K):分母为 0,pullback_depth = null,正常输出其他字段。
4
持续回调穿透 EMA_slow:不触发 direction 重置(direction 由步骤 A 独立判断);若下一根 K 线 EMA 排列仍为涨势,segment_state 继续保持 pullback,等待突破 prev_extreme 后计新段。
5
多空快速互切(价格在三线附近震荡):每次方向切换均触发重置,segment_count 从 1 重新计。这会导致频繁 segment_count=1;可通过信号层的"连续确认根数"过滤,不在本算法层处理。