AI 原生量化投研平台AI-native quantitative research platform
正在加载…Loading…
页面仍在加载,可以继续等待,或重新加载。The page is still loading. You can keep waiting or reload.
部分页面资源未能加载,请重新加载。Some page resources could not load. Please reload.
设备当前处于离线状态,恢复连接后可以继续等待或重新加载。Your device is offline. Once connected, you can keep waiting or reload.
K线形态类技术指标因子
23 个字段 · 主键 date + instrument
单根到三根 K 线的形态特征:影线比例、实体比例与收盘位置刻画日内多空争夺的结果,跳空幅度刻画隔夜情绪冲击, 十字星 / 锤子线 / 倒锤子线 / 射击之星 / 吞没 / 刺透 / 乌云盖顶 / 星线 / 红三兵 / 三只乌鸦是经典反转与延续形态标记, 内包线与外包线刻画波动的收敛与放大,连续上涨天数刻画短期情绪动量。 本类因子窗口极短,噪声大但换手信息足,适合与中长周期趋势因子搭配。
- 因子数量:21 个因子 / 21 个数据列
- 主键:
date+instrument(按cn_stock_instruments对齐全市场标的)- 数据起始:2010-01-01,日频增量更新
- 复权口径:后复权(
cn_stock_bar1d全表统一)
| 上游表 | 用途 | 本表用到的字段 |
|---|---|---|
cn_stock_bar1d | 后复权日行情,全部因子的计算输入 | date, instrument, open, high, low, close |
cn_stock_instruments | 全市场标的清单,决定本表每日的 date / instrument 组合 | date, instrument |
cn_stock_bar1d为分区表,SQL 的 date 过滤由dai.query(filters={"date": [...]})下推完成。
| # | 因子中文名 | 字段名 | 参数 | 因子逻辑 | 所属因子族 |
|---|---|---|---|---|---|
| 1 | 上影线比例 | upper_shadow | 1 | 上影线占振幅比例(上方抛压) | 影线与实体形态 |
| 2 | 下影线比例 | lower_shadow | 1 | 下影线占振幅比例(下方承接) | 影线与实体形态 |
| 3 | 收盘位置 | body_pos | 1 | 收盘价在日内振幅区间的位置 | 影线与实体形态 |
| 4 | 十字星 | doji | 1 | 实体极小的 K 线(多空平衡)为 1 | 影线与实体形态 |
| 5 | 锤子线 | hammer | 1 | 经典锤子线形态(底部反转) | 锤子线形态 / 连续上涨天数 |
| 6 | 连续上涨天数 | rise_count | 1 | 连续阳线天数(情绪动量) | 锤子线形态 / 连续上涨天数 |
| 7 | 实体比例 | body_ratio | 1 | K 线实体占振幅比例(趋势 K 线越强越大) | 实体与跳空形态 |
| 8 | 光头光脚线 | marubozu | 1 | 实体占满振幅的大阳/大阴线(单边强势)为 1 | 实体与跳空形态 |
| 9 | 跳空幅度 | gap_ratio | 1 | 开盘相对前收的跳空幅度(隔夜情绪冲击) | 实体与跳空形态 |
| 10 | 看涨吞没 | bullish_engulfing | 1 | 阳线实体完全吞没前一阴线实体(底部反转)为 1 | 包含与吞没形态 |
| 11 | 看跌吞没 | bearish_engulfing | 1 | 阴线实体完全吞没前一阳线实体(顶部反转)为 1 | 包含与吞没形态 |
| 12 | 内包线 | inside_bar | 1 | 高低点被前一根完全包含(波动收敛、待突破)为 1 | 包含与吞没形态 |
| 13 | 外包线 | outside_bar | 1 | 高低点完全包含前一根(波动放大、多空分歧)为 1 | 包含与吞没形态 |
| 14 | 倒锤子线 | inverted_hammer | 2 | 下跌市况中的长上影小实体(底部反转)为 +100 | 单根反转形态 |
| 15 | 射击之星 | shooting_star | 2 | 上涨市况中向上跳空的长上影小实体(顶部反转)为 −100 | 单根反转形态 |
| 16 | 刺透形态 | piercing_line | 2 | 低开阳线收回前一阴线实体中点之上(底部反转)为 1 | 两根K线反转形态 |
| 17 | 乌云盖顶 | dark_cloud_cover | 2 | 高开阴线收进前一阳线实体中点之下(顶部反转)为 −100 | 两根K线反转形态 |
| 18 | 早晨之星 | morning_star | 3 | 大阴 + 小实体跳空 + 大阳收回的三 K 线底部反转为 +100 | 星线与三K线形态 |
| 19 | 黄昏之星 | evening_star | 3 | 大阳 + 小实体跳空 + 大阴收回的三 K 线顶部反转为 −100 | 星线与三K线形态 |
| 20 | 红三兵 | three_red_soldiers | 3 | 三连阳且开收逐级抬高(趋势确立)为 +100 | 星线与三K线形态 |
| 21 | 三只乌鸦 | three_black_crows | 3 | 三连阴且开收逐级走低(趋势转弱)为 −100 | 星线与三K线形态 |
参数列指形态识别需要的 K 线根数:1 = 单根,2 = 当日 + 前一日,3 = 当日 + 前两日。
本表的形态标记列有两种取值口径,混在同一张表里是有意为之(自研形态用可读的 0/1,TA-Lib 移植形态保留原口径便于与外部结果对齐),建模前请按列区分:
| 口径 | 取值 | 涉及列 |
|---|---|---|
| 自研 SQL 形态 | 0 / 1(命中为 1) | doji、marubozu、bullish_engulfing、bearish_engulfing、inside_bar、outside_bar、piercing_line |
| TA-Lib 移植形态 | 0 / ±100(看涨 +100、看跌 −100) | hammer、inverted_hammer、shooting_star、dark_cloud_cover、morning_star、evening_star、three_red_soldiers、three_black_crows |
m_lag 为 NULL)时显式写成 NULL,避免把"无法判定"误当成"未命中"。body_ratio、gap_ratio、upper_shadow、lower_shadow、body_pos、rise_count 为连续值列,不是 0/1 标记。公式:上影线比例 = (H − MAX(O,C)) / (H − L);下影线比例 = (MIN(O,C) − L) / (H − L);收盘位置 = (C − L) / (H − L);十字星 = 1(|C − O| / (H − L) ≤ 0.1)
输出列(4):upper_shadow、lower_shadow、body_pos、doji
SELECT date, instrument, (high - greatest(open, close)) / NULLIF(high - low, 0) AS upper_shadow, (least(open, close) - low) / NULLIF(high - low, 0) AS lower_shadow, (close - low) / NULLIF(high - low, 0) AS body_pos, if(abs(close - open) / NULLIF(high - low, 0) <= 0.1, 1, 0) AS dojiFROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument公式:hammer 为 TA-Lib 标准锤子线识别(小实体、长下影、上影极短);rise_count 为当前连续收阳(Close > 前Close)天数
输出列(2):hammer、rise_count
SELECT date, instrument, m_ta_hammer(open, high, low, close) AS hammer, m_consecutive_rise_count(close) AS rise_countFROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument公式:实体比例 = |C − O| / (H − L);光头光脚线 = 1(|C − O| ≥ 0.9 × (H − L) 且 H > L);跳空幅度 = (O − 前C) / 前C
输出列(3):body_ratio、marubozu、gap_ratio
SELECT date, instrument, abs(close - open) / NULLIF(high - low, 0) AS body_ratio, CASE WHEN high <= low THEN NULL WHEN abs(close - open) >= 0.9 * (high - low) THEN 1 ELSE 0 END AS marubozu, (open - m_lag(close, 1)) / NULLIF(m_lag(close, 1), 0) AS gap_ratioFROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrumentmarubozu 用 high <= low THEN NULL 显式排除一字板,否则 |C − O| ≥ 0.9 × 0 恒真,会把全部一字板误判成光头光脚线。
公式:看涨吞没 = 前阴 + 今阳 + 今实体完全覆盖前实体;看跌吞没 = 前阳 + 今阴 + 今实体完全覆盖前实体;内包线 = 今高低点被前高低点包含;外包线 = 今高低点包含前高低点
输出列(4):bullish_engulfing、bearish_engulfing、inside_bar、outside_bar
SELECT date, instrument, CASE WHEN m_lag(close, 1) IS NULL THEN NULL WHEN m_lag(close, 1) < m_lag(open, 1) AND close > open AND close >= m_lag(open, 1) AND open <= m_lag(close, 1) THEN 1 ELSE 0 END AS bullish_engulfing, CASE WHEN m_lag(close, 1) IS NULL THEN NULL WHEN m_lag(close, 1) > m_lag(open, 1) AND close < open AND close <= m_lag(open, 1) AND open >= m_lag(close, 1) THEN 1 ELSE 0 END AS bearish_engulfing, CASE WHEN m_lag(high, 1) IS NULL THEN NULL WHEN high <= m_lag(high, 1) AND low >= m_lag(low, 1) AND (high < m_lag(high, 1) OR low > m_lag(low, 1)) THEN 1 ELSE 0 END AS inside_bar, CASE WHEN m_lag(high, 1) IS NULL THEN NULL WHEN high >= m_lag(high, 1) AND low <= m_lag(low, 1) AND (high > m_lag(high, 1) OR low < m_lag(low, 1)) THEN 1 ELSE 0 END AS outside_barFROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrumentinside_bar / outside_bar 各自额外要求"至少一侧严格超出",因此两列互斥:高低点与前一根完全相同的样本(一字板连板常见)两列都是 0,不会同时命中。
公式:倒锤子线 / 射击之星均为 TA-Lib 标准识别(小实体、长上影、下影极短);倒锤子线出现在下跌市况(看涨,+100),射击之星出现在上涨市况且向上跳空(看跌,−100)
输出列(2):inverted_hammer、shooting_star
SELECT date, instrument, m_ta_inverted_hammer(open, high, low, close) AS inverted_hammer, m_ta_shooting_star(open, high, low, close) AS shooting_starFROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument倒锤子线与射击之星的单根形态完全相同,区别只在前置市况:TA-Lib 用前一根的相对位置判断上涨/下跌,因此两列不会同时命中,可以直接相加成一个"长上影反转"方向因子。
公式:刺透形态 = 前阴 + 今低开于前收之下 + 今阳收在前实体中点之上但未越过前开(看涨,1);乌云盖顶为 TA-Lib 标准识别,前阳 + 今高开于前收之上 + 今阴收进前实体中点之下(看跌,−100)
输出列(2):piercing_line、dark_cloud_cover
SELECT date, instrument, CASE WHEN m_lag(close, 1) IS NULL THEN NULL WHEN m_lag(close, 1) < m_lag(open, 1) AND close > open AND open < m_lag(close, 1) AND close > (m_lag(open, 1) + m_lag(close, 1)) / 2 AND close < m_lag(open, 1) THEN 1 ELSE 0 END AS piercing_line, m_ta_dark_cloud_cover(open, high, low, close) AS dark_cloud_coverFROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument这一族是一对镜像形态,但两列口径不同:piercing_line 为自研 0/1,dark_cloud_cover 直接调用 TA-Lib 算子(0/−100)。
DAI 提供了 m_ta_dark_cloud_cover 但没有对应的 piercing 算子,所以刺透形态按经典定义用 SQL 实现。
公式:均为 TA-Lib 标准三根 K 线识别。早晨之星 = 大阴 + 小实体向下跳空 + 大阳收回(看涨,+100);黄昏之星为其镜像(看跌,−100);红三兵 = 三连阳且开收逐级抬高(看涨,+100);三只乌鸦 = 三连阴且开收逐级走低(看跌,−100)
输出列(4):morning_star、evening_star、three_red_soldiers、three_black_crows
SELECT date, instrument, m_ta_morning_star(open, high, low, close) AS morning_star, m_ta_evening_star(open, high, low, close) AS evening_star, m_ta_3red_soldiers(open, high, low, close) AS three_red_soldiers, m_ta_3black_crows(open, high, low, close) AS three_black_crowsFROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument本族是全表最稀疏的一族(命中率 0.01% ~ 0.4%,见第 5 节),不适合单独做截面因子,建议按方向聚合或只作为事件标记使用。
cn_stock_bar1d(后复权,WHERE close IS NOT NULL) → 7 组因子族 SQL 并行执行(joblib loky, n_jobs=8) → 按 cn_stock_instruments 左连接对齐全市场标的 → schema 归一化(列序 / 类型 / 缺失值) → dai_write 按 date 的年份分区落库create(),自 2010-01-01 起按 2 年一段滚动执行,每段结束后 gc.collect() 释放内存。build(),默认覆盖最近 5 个自然日;落库前跑 tester.py,落库后更新前端文档。窗口算子只在查询下推后的行集上计算,所以每次计算都会向前多取一段行情:
| 参数 | 取值 | 说明 |
|---|---|---|
lookback_days | 200 个自然日(≈ 133 个交易日) | 本表最长预热需求约 13 个交易日 |
最长预热需求来自 TA-Lib 形态算子:星线 / 红三兵 / 三只乌鸦 / 乌云盖顶 除了要看 2~3 根 K 线,
还要一段实体长度均值来判定"大实体 / 小实体"(TA-Lib 的 BodyLong / BodyShort 默认 avgperiod = 10),
合计约 13 个交易日。自研 SQL 形态最多只用到 m_lag(·, 1),1 个交易日即可预热。
多读一段历史不改变任何输出值(窗口算子只向前看),只是把区间首日的"本可避免的缺失"消掉。 EMA / RSI / ATR / MACD / TRIX 属于 IIR 递推算子,理论上预热期无限长,因此这些表的冗余按 约 5 倍最长周期取值,而非刚好等于窗口长度。
cn_stock_bar1d 在停牌日会保留一行、但 open/high/low/close/amount 全为 NULL、volume 为 0。
m_ta_* 递推类算子只要吃到一个 NULL,之后就永久输出 NULL。因此所有 SQL 统一加
WHERE close IS NOT NULL,把停牌行从计算输入中剔除(此时 m_lag(close, 1) 指向上一个交易日,
符合技术指标的常规口径)。
实测(2024-01 全市场,回溯起点 2021-06):
| 处理方式 | bbands_middle_20 | atr14 | kdj_j_9 | macd_diff_12_26_9 |
|---|---|---|---|---|
| 不加过滤 | 88.3% | 88.3% | 88.4% | 88.1% |
加 WHERE close IS NOT NULL | 99.7% | 99.7% | 99.7% | 99.5% |
对本表的形态因子还有一层额外含义:gap_ratio、吞没 / 包含 / 刺透形态都以"前一交易日"为参照,
剔除停牌行后 m_lag 跨过停牌期直接指向上一个真实交易日,跳空幅度不会被停牌切断。
本表不含累计型因子,全部因子都是固定长度的滚动窗口计算,因此只受 lookback_days 影响。
落库前以 cn_stock_instruments 为基准左连接,因此每个交易日都是全市场标的的完整行,
停牌股与上市不足窗口长度的新股在对应因子列上为 NULL。入库校验要求单因子整体覆盖度 ≥ 85%
(tester.py 关键测试点),单日覆盖度 ≥ 80%(非关键,仅告警)。
upper_shadow/lower_shadow/body_pos/body_ratio 的分母为当日振幅 (H − L),一字板(H = L)样本经 NULLIF 保护后为 NULL,这是本类覆盖度损失的主要来源。np.double,以便 normalize() 用 NaN 表示"无法判定"而非误填 0;自研列的 CASE WHEN m_lag(...) IS NULL THEN NULL 分支就是为此显式写出来的。marubozu、星线族等条件式全部用乘法形式(|C − O| ≥ 0.9 × (H − L))而不是除法比值,从源头避免除零,tester.py 的 inf 检查因此恒为通过。m_ta_hammer / m_ta_inverted_hammer / m_ta_shooting_star / m_ta_dark_cloud_cover / m_ta_morning_star / m_ta_evening_star / m_ta_3red_soldiers / m_ta_3black_crows)由 DAI 提供,输出为 TA-Lib 形态识别值(0 / ±100);rise_count 调用 m_consecutive_rise_count,输出当前连续收阳天数。doji / marubozu / 吞没 / 包含 / 刺透等没有对应算子的形态一律按经典定义用 SQL 实现,所以本表出现 0/1 与 0/±100 两种口径并存(见 2.1 节)。实测区间 2026-09-07 ~ 2026-09-17(9 个交易日、50052 行,已按 cn_stock_instruments 对齐全市场标的):
| 指标 | 数值 |
|---|---|
| 因子列数 | 21 |
| 最低覆盖度 | 99.72%(upper_shadow / lower_shadow / body_pos / body_ratio / marubozu) |
| 中位覆盖度 | 99.77% |
| 最高覆盖度 | 99.79% |
| 覆盖度 < 85% 的列数 | 0 |
tester.py 关键测试点 | ✅ 通过 |
覆盖度最低的一档是分母为振幅 (H − L) 的 5 列(99.72%),其次是依赖 m_lag(·, 1) 的 6 列(99.77%),
TA-Lib 形态列与 doji / rise_count 最高(99.79%)。缺失主要来自当日停牌与上市首日,
逐列明细见 testdata/coverage_report.md,数据示例见 testdata/sample_data.csv。
形态标记列本质是稀疏事件,覆盖度高不等于信息密度高,建模前请先看命中率:
| 形态列 | 命中率 | 形态列 | 命中率 |
|---|---|---|---|
inside_bar | 17.45% | piercing_line | 2.09% |
doji | 9.79% | inverted_hammer | 1.81% |
outside_bar | 9.28% | morning_star | 0.41% |
bullish_engulfing | 5.78% | shooting_star | 0.27% |
bearish_engulfing | 4.66% | evening_star | 0.21% |
marubozu | 4.11% | dark_cloud_cover | 0.15% |
hammer | 2.58% | three_red_soldiers | 0.02% |
three_black_crows | 0.01% |
连续值列的非零占比:body_ratio 97.5%、body_pos 97.4%、lower_shadow 93.2%、upper_shadow 89.2%、gap_ratio 87.0%、rise_count 42.7%。
{{sample_data}}
hammer 等 TA-Lib 列取值 0/±100,自研列取值 0/1,直接混在一起做加权或求和会让 TA-Lib 列的权重被放大 100 倍。建议统一成 sign(x)(−1/0/+1)后再聚合。看涨形态计数 = bullish_engulfing + piercing_line + sign(hammer) + sign(inverted_hammer) + sign(morning_star) + sign(three_red_soldiers),
看跌形态计数 = bearish_engulfing − sign(shooting_star) − sign(dark_cloud_cover) − sign(evening_star) − sign(three_black_crows),
或用 m_sum(形态, 5) 做几日内的事件累计。doji、marubozu、inside_bar、outside_bar 没有方向,
属于"波动状态"而非"看涨/看跌",不要并进方向计数。c_zscore(因子, group=date) 或 c_rank(因子, group=date) 处理,或改用同族的比值型因子。NULLIF 保护,但小分母仍会放大尾部,建议按日做分位数截断;
gap_ratio 在 A 股受涨跌停限制天然截断在 ±20% 附近,但 ST 股与新股不同档位混用时仍建议分组处理。inverted_hammer / shooting_star、hammer / 吊颈类形态的单根 K 线形状相同,
TA-Lib 靠前置趋势区分方向。用在自己的模型里时,建议与趋势类因子(均线、动量)交叉后再判读,
单看形态标记的方向性会不稳定。body_ratio 与 doji、inside_bar 与 outside_bar),
建模前建议按 IC / 相关性 / 特征重要性做筛选,而不是把全部列直接喂给模型。SELECT date, instrument, upper_shadow, lower_shadow, body_pos, doji, hammer FROM cn_stock_factors_ta_pattern WHERE date >= '2026-10-06' ORDER BY date LIMIT 100
SELECT date, instrument, upper_shadow, lower_shadow, body_pos, doji, hammer FROM cn_stock_factors_ta_pattern WHERE date >= '2026-10-06' ORDER BY date LIMIT 100