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.
量价类技术指标因子
33 个字段 · 主键 date + instrument
价与量的联动特征:量比 / 成交额变化率 / 换手率放大倍数度量量能相对自身历史的异动,量价相关系数与回归斜率度量价量同步性,OBV / WAD / PVT / WVAD / MFI 从资金流入流出方向累计多空力量,单笔成交额比刻画大单参与度。
- 因子数量:31 个因子 / 31 个数据列
- 主键:
date+instrument(按cn_stock_instruments对齐全市场标的)- 数据起始:2010-01-01,日频增量更新
- 复权口径:后复权(
cn_stock_bar1d全表统一)
| 上游表 | 用途 | 本表用到的字段 |
|---|---|---|
cn_stock_bar1d | 后复权日行情,全部因子的计算输入 | date, instrument, open, high, low, close, volume, amount, turn, deal_number |
cn_stock_instruments | 全市场标的清单,决定本表每日的 date / instrument 组合 | date, instrument |
cn_stock_bar1d为分区表,SQL 的 date 过滤由dai.query(filters={"date": [...]})下推完成。
| # | 因子中文名 | 字段名 | 参数 | 因子逻辑 | 所属因子族 |
|---|---|---|---|---|---|
| 1 | 量比 | vol_ratio_5 | 5 | 当日成交量 / 5 日均量 | 量比族 |
| 2 | 量比 | vol_ratio_10 | 10 | 当日成交量 / 10 日均量 | 量比族 |
| 3 | 量比 | vol_ratio_20 | 20 | 当日成交量 / 20 日均量 | 量比族 |
| 4 | 量价相关系数 | corr_vol_price_10 | 10 | 收盘价与成交量的 10 日滚动相关性 | 量价相关系数族 |
| 5 | 量价相关系数 | corr_vol_price_20 | 20 | 收盘价与成交量的 20 日滚动相关性 | 量价相关系数族 |
| 6 | 量价相关系数 | corr_vol_price_60 | 60 | 收盘价与成交量的 60 日滚动相关性 | 量价相关系数族 |
| 7 | 量价回归斜率 | regr_slope_10 | 10 | 收盘价对成交量的 10 日回归斜率 | 量价回归斜率族 |
| 8 | 量价回归斜率 | regr_slope_20 | 20 | 收盘价对成交量的 20 日回归斜率 | 量价回归斜率族 |
| 9 | 量价回归斜率 | regr_slope_60 | 60 | 收盘价对成交量的 60 日回归斜率 | 量价回归斜率族 |
| 10 | 成交额变化率 | amt_ratio_5 | 5 | 当日成交额 / 5 日均额 − 1 | 成交额变化率族 |
| 11 | 成交额变化率 | amt_ratio_20 | 20 | 当日成交额 / 20 日均额 − 1 | 成交额变化率族 |
| 12 | 成交额变化率 | amt_ratio_60 | 60 | 当日成交额 / 60 日均额 − 1 | 成交额变化率族 |
| 13 | 换手率放大倍数 | turn_ratio_20 | 20 | 当日换手 / 20 日均换手 | 换手率放大倍数族 |
| 14 | 换手率放大倍数 | turn_ratio_60 | 60 | 当日换手 / 60 日均换手 | 换手率放大倍数族 |
| 15 | OBV 能量潮动量 | obv_mom_10 | 10 | 10 日 OBV 变化量 / 10 日均量 | OBV 能量潮动量族 |
| 16 | OBV 能量潮动量 | obv_mom_20 | 20 | 20 日 OBV 变化量 / 20 日均量 | OBV 能量潮动量族 |
| 17 | OBV 能量潮动量 | obv_mom_60 | 60 | 60 日 OBV 变化量 / 60 日均量 | OBV 能量潮动量族 |
| 18 | 单笔成交额比 | avg_deal_ratio_5 | 5 | 单笔成交额相对 5 日均值 | 单笔成交额比族 |
| 19 | 单笔成交额比 | avg_deal_ratio_20 | 20 | 单笔成交额相对 20 日均值 | 单笔成交额比族 |
| 20 | 单笔成交额比 | avg_deal_ratio_60 | 60 | 单笔成交额相对 60 日均值 | 单笔成交额比族 |
| 21 | 威廉变异离散量 | wvad6 | 6 | 多空强度×成交量再差分 | WVAD / MFI / TAPI 组合 |
| 22 | 资金流向指标 | mfi14 | 14 | 典型价×量的多空资金占比 | WVAD / MFI / TAPI 组合 |
| 23 | TAPI 加权指数成交值 | tapi | 1 | 成交额 / 收盘价 | WVAD / MFI / TAPI 组合 |
| 24 | 平衡成交量 | obv | None | 收盘价涨跌方向累计成交量 | OBV 平衡成交量与其均线族 |
| 25 | 平衡成交量移动均值 | maobv_6 | 6 | OBV 的 6 日简单移动均值 | OBV 平衡成交量与其均线族 |
| 26 | 平衡成交量移动均值 | maobv_14 | 14 | OBV 的 14 日简单移动均值 | OBV 平衡成交量与其均线族 |
| 27 | 平衡成交量移动均值 | maobv_20 | 20 | OBV 的 20 日简单移动均值 | OBV 平衡成交量与其均线族 |
| 28 | 平衡成交量移动均值 | maobv_30 | 30 | OBV 的 30 日简单移动均值 | OBV 平衡成交量与其均线族 |
| 29 | 平衡成交量移动均值 | maobv_60 | 60 | OBV 的 60 日简单移动均值 | OBV 平衡成交量与其均线族 |
| 30 | 威廉聚散指标 | wad | 累计 | 资金流入流出的持续性累计 | WAD 威廉聚散指标 / PVT 量价趋势指标 |
| 31 | 量价趋势指标 | pvt | 累计 | 涨跌幅×成交量累计 | WAD 威廉聚散指标 / PVT 量价趋势指标 |
公式:量比_N = Volume / MA_N(Volume)
输出列(3):vol_ratio_5、vol_ratio_10、vol_ratio_20
SELECT date, instrument, volume / NULLIF(m_avg(volume, 5), 0) AS vol_ratio_5, volume / NULLIF(m_avg(volume, 10), 0) AS vol_ratio_10, volume / NULLIF(m_avg(volume, 20), 0) AS vol_ratio_20FROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument公式:Corr_N = CORR_N(Close, Volume)
输出列(3):corr_vol_price_10、corr_vol_price_20、corr_vol_price_60
SELECT date, instrument, m_corr(close, volume, 10) AS corr_vol_price_10, m_corr(close, volume, 20) AS corr_vol_price_20, m_corr(close, volume, 60) AS corr_vol_price_60FROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument公式:Slope_N = REGR_SLOPE_N(Close ~ Volume)
输出列(3):regr_slope_10、regr_slope_20、regr_slope_60
SELECT date, instrument, m_regr_slope(close, volume, 10) AS regr_slope_10, m_regr_slope(close, volume, 20) AS regr_slope_20, m_regr_slope(close, volume, 60) AS regr_slope_60FROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument公式:AmtRatio_N = Amount / MA_N(Amount) − 1
输出列(3):amt_ratio_5、amt_ratio_20、amt_ratio_60
SELECT date, instrument, amount / NULLIF(m_avg(amount, 5), 0) - 1 AS amt_ratio_5, amount / NULLIF(m_avg(amount, 20), 0) - 1 AS amt_ratio_20, amount / NULLIF(m_avg(amount, 60), 0) - 1 AS amt_ratio_60FROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument公式:TurnRatio_N = Turn / MA_N(Turn)
输出列(2):turn_ratio_20、turn_ratio_60
SELECT date, instrument, turn / NULLIF(m_avg(turn, 20), 0) AS turn_ratio_20, turn / NULLIF(m_avg(turn, 60), 0) AS turn_ratio_60FROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument公式:OBV_Mom_N = (OBV − OBV_N日前) / MA_N(Volume)
输出列(3):obv_mom_10、obv_mom_20、obv_mom_60
SELECT date, instrument, (m_ta_obv(close, volume) - m_lag(m_ta_obv(close, volume), 10)) / NULLIF(m_avg(volume, 10), 0) AS obv_mom_10, (m_ta_obv(close, volume) - m_lag(m_ta_obv(close, volume), 20)) / NULLIF(m_avg(volume, 20), 0) AS obv_mom_20, (m_ta_obv(close, volume) - m_lag(m_ta_obv(close, volume), 60)) / NULLIF(m_avg(volume, 60), 0) AS obv_mom_60FROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument公式:AvgDeal_N = (Amount / DealNumber) / MA_N(Amount / DealNumber)
输出列(3):avg_deal_ratio_5、avg_deal_ratio_20、avg_deal_ratio_60
SELECT date, instrument, (amount / NULLIF(deal_number, 0)) / NULLIF(m_avg(amount / NULLIF(deal_number, 0), 5), 0) AS avg_deal_ratio_5, (amount / NULLIF(deal_number, 0)) / NULLIF(m_avg(amount / NULLIF(deal_number, 0), 20), 0) AS avg_deal_ratio_20, (amount / NULLIF(deal_number, 0)) / NULLIF(m_avg(amount / NULLIF(deal_number, 0), 60), 0) AS avg_deal_ratio_60FROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument公式:WVAD = Δ6(SUM((C−O)/(H−L) × Volume, 6));MFI = m_ta_mfi(H, L, C, V, 14);TAPI = Amount / Close
输出列(3):wvad6、mfi14、tapi
SELECT date, instrument, m_delta(m_sum((close - open) / NULLIF(high - low, 0) * volume, 6), 6) AS wvad6, m_ta_mfi(high, low, close, volume, 14) AS mfi14, amount / NULLIF(close, 0) AS tapiFROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument公式:OBV = 累计(IF(C>前C, +V, IF(C<前C, −V, 0)));MAOBV_N = SMA(OBV, N)
输出列(6):obv、maobv_6、maobv_14、maobv_20、maobv_30、maobv_60
累计型因子族:builder 用固定锚点
cum_anchor_date查询。
SELECT date, instrument, m_ta_obv(close, volume) AS obv, m_ta_sma(m_ta_obv(close, volume), 6) AS maobv_6, m_ta_sma(m_ta_obv(close, volume), 14) AS maobv_14, m_ta_sma(m_ta_obv(close, volume), 20) AS maobv_20, m_ta_sma(m_ta_obv(close, volume), 30) AS maobv_30, m_ta_sma(m_ta_obv(close, volume), 60) AS maobv_60FROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrument公式:AD = IF(C>前C, C−MIN(前C, L), IF(C<前C, C−MAX(前C, H), 0));WAD = 累计(AD);PVT = 累计((Close/前Close − 1) × Volume)
输出列(2):wad、pvt
累计型因子族:builder 用固定锚点
cum_anchor_date查询。
SELECT date, instrument, SUM(CASE WHEN close > m_lag(close, 1) THEN close - least(m_lag(close, 1), low) WHEN close < m_lag(close, 1) THEN close - greatest(m_lag(close, 1), high) ELSE 0 END) OVER (PARTITION BY instrument ORDER BY date) AS wad, SUM((close / NULLIF(m_lag(close, 1), 0) - 1) * volume) OVER (PARTITION BY instrument ORDER BY date) AS pvtFROM cn_stock_bar1dWHERE close IS NOT NULLORDER BY date, instrumentcn_stock_bar1d(后复权,WHERE close IS NOT NULL) → 10 组因子族 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 | 300 个自然日(≈ 200 个交易日) | 本表最长窗口 / 预热需求约 60 个交易日 |
多读一段历史不改变任何输出值(窗口算子只向前看),只是把区间首日的"本可避免的缺失"消掉。 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% |
obv、maobv_*、wad、pvt 是从序列起点累加的因子,累计起点变了绝对水平就变。为保证历史构建与每日增量构建落库的值一致,这四族固定从 cum_anchor_date = 2010-01-01 起算(与本因子库数据起始日一致),而不是跟着增量窗口的回溯起点漂移。
推论:2010 年前上市的股票,其累计值起点为 2010-01-01 而非上市首日;obv_mom_* 是 OBV 的差分,锚点在差分中被抵消,所以不受影响、也无需固定锚点。
落库前以 cn_stock_instruments 为基准左连接,因此每个交易日都是全市场标的的完整行,
停牌股与上市不足窗口长度的新股在对应因子列上为 NULL。入库校验要求单因子整体覆盖度 ≥ 85%
(tester.py 关键测试点),单日覆盖度 ≥ 80%(非关键,仅告警)。
obv、maobv_*、wad、pvt 是从序列起点开始的累计值,其绝对水平依赖累计起点。为保证历史构建与每日增量构建的结果一致,这四族固定从 cum_anchor_date(默认 2010-01-01,与本因子库起始日一致)开始累计,而不是从增量窗口的回溯起点开始。2010 年前上市的股票,其累计值起点为 2010-01-01 而非上市首日。obv_mom_* 是 OBV 的差分再除以均量,锚点在差分中被抵消,因此无需固定锚点。avg_deal_ratio_* 依赖成交笔数字段。上游表中该字段名为 deal_number(不是因子文档写的 deal_num),本表已修正;停牌或缺笔数的样本经 NULLIF 保护后为 NULL。vol_ratio_5 的口径为日频 5 日均量比,替代了部分上游表用分钟表 7200 分钟窗口近似 5 日的写法。实测区间 2026-09-07 ~ 2026-09-17(9 个交易日、50052 行,已按 cn_stock_instruments 对齐全市场标的):
| 指标 | 数值 |
|---|---|
| 因子列数 | 31 |
| 最低覆盖度 | 93.23%(avg_deal_ratio_60) |
| 中位覆盖度 | 99.50% |
| 最高覆盖度 | 99.79% |
| 覆盖度 < 85% 的列数 | 0 |
tester.py 关键测试点 | ✅ 通过 |
覆盖度最低的三列:avg_deal_ratio_60(93.2%)、avg_deal_ratio_20(93.5%)、avg_deal_ratio_5(93.6%)。缺失主要来自上市不足窗口长度的新股与当日停牌,逐列明细见 testdata/coverage_report.md,数据示例见 testdata/sample_data.csv。
{{sample_data}}
c_zscore(因子, group=date) 或 c_rank(因子, group=date) 处理,或改用同族的比值型因子。NULLIF 保护,但小分母仍会放大尾部,建议按日做分位数截断。SELECT date, instrument, vol_ratio_5, vol_ratio_10, vol_ratio_20, corr_vol_price_10, corr_vol_price_20 FROM cn_stock_factors_ta_volume_price WHERE date >= '2026-10-06' ORDER BY date LIMIT 100
SELECT date, instrument, vol_ratio_5, vol_ratio_10, vol_ratio_20, corr_vol_price_10, corr_vol_price_20 FROM cn_stock_factors_ta_volume_price WHERE date >= '2026-10-06' ORDER BY date LIMIT 100