数据管线模块(scripts/)
数据管线负责从外部数据源获取股票行情和财务数据,计算技术指标和基本面评分,并构建离线快照文件供后端服务使用。同时包含宏观指标、板块数据、信号候选池和信号绩效的构建脚本。
目录结构
text
scripts/
├── config.yaml # 股票池与获取配置
├── yfinance_client.py # yfinance API 封装
├── feature_engine.py # 技术指标与形态识别
├── scorer.py # 综合评分 + 价值-成长复合评分
├── build_snapshot.py # 快照构建入口(编排器)
├── build_macro.py # 宏观指标数据构建
├── build_sectors.py # 板块 ETF 数据构建
├── rt_manager.py # 实时数据管理器
├── rt_providers.py # 实时数据源抽象层(yfinance / 阿里云)
├── rt_push_providers.py # 实时推送源实现(xx1 / xx2 / 阿里云)
├── ashen_client.py # xx WebSocket 客户端
├── signal_candidate_pool.py # 信号候选池离线打分
├── signal_outcomes.py # 信号绩效计算(MFE/MAE/前向收益)
├── dev_server.sh # 开发服务器管理脚本
└── daily5_alpha_select.py # Alpha 因子选股脚本
数据流
text
config.yaml
↓
yfinance_client.py ──获取──→ 原始行情 + 股票信息 + 财务指标
↓
feature_engine.py ──计算──→ 技术指标(~80 列)+ 高级指标(MACD/RSI/BB/VWAP/MFI/Williams %R/ADX/CCI/Stochastic/OBV/Chaikin/ATR)
↓
scorer.py ──评分──→ signal_score(0-100)+ value_quality_score + piotroski_score
↓
build_snapshot.py ──输出──→ data.parquet + history.parquet
build_macro.py ──获取──→ macro.parquet(VIX / 10Y / DXY / SPX)
build_sectors.py ──获取──→ sectors.parquet(14 个板块/风格 ETF)
signal_candidate_pool.py ──打分──→ candidates.parquet / candidates.csv(每日 Top 20)
signal_outcomes.py ──计算──→ MFE/MAE + 1/3/5/10 日前向收益
各文件详解
config.yaml --- 配置中心
定义股票池、数据获取参数、实时数据配置和预警配置。
股票池(约 200 只,分 9 组):
| 分组 | 说明 | 示例 |
|---|---|---|
| tech | 科技/半导体(70+只) | AAPL, NVDA, MSFT, TSLA, ARM, TSM |
| finance | 金融/支付 | JPM, V, MA, BRK-B, COIN |
| healthcare | 医疗/生物科技 | JNJ, UNH, LLY, MRNA |
| energy | 能源/资源 | XOM, CVX, COP, NEM, FCX |
| industrial | 工业/航空/国防 | CAT, BA, GE, HON, RTX |
| consumer | 消费/零售/餐饮 | PG, KO, MCD, WMT, NFLX |
| infra | 通信/公用事业/REIT | T, VZ, NEE, AMT, EQIX |
| aerospace | 太空/航空/国防 | RKLB, ASTS, LUNR, LHX, HEI |
| other | 汽车/交通/其他 | F, RIVN, UBER, BIDU, PDD |
获取参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
| history_period | 2y | 历史数据时间跨度 |
| batch_size | 20 | 每批获取股票数量 |
| batch_delay | 2.0s | 批次间隔 |
| max_retries | 2 | 最大重试次数 |
| request_timeout | 30s | 单次请求超时 |
多时间周期配置:
| 时间周期 | interval | period |
|---|---|---|
| 日线 | 1d | 2y |
| 周线 | 1wk | 5y |
| 60 分钟 | 60m | 730d |
| 30 分钟 | 30m | 60d |
| 15 分钟 | 15m | 60d |
| 5 分钟 | 5m | 60d |
实时数据配置:
| 配置 | 说明 |
|---|---|
realtime.provider |
数据源选择:free (yfinance) / premium (aliyun) |
realtime.push.provider |
推送源选择:xx1 / xx2 / aliyun |
realtime.trading_hours |
交易时段定义(盘前/盘中/盘后) |
realtime.update_interval_sec |
报价更新间隔(秒) |
alerts.enabled |
预警引擎开关 |
alerts.db_path |
SQLite 数据库路径 |
alerts.max_rules_per_device |
每设备最大规则数(50) |
alerts.retention_days |
事件保留天数(30) |
yfinance_client.py --- 数据获取
封装 yfinance API,提供批量获取、重试和标准化功能。
核心函数:
| 函数 | 用途 | 返回 |
|---|---|---|
load_config() |
加载 config.yaml | dict |
get_stock_pool() |
提取去重后的股票列表 | liststr |
fetch_history_batch() |
批量下载历史行情 | dictstr, DataFrame |
fetch_stock_info() |
获取单只股票基本信息 | StockInfo |
fetch_financial_metrics() |
获取财务指标 | dict |
fetch_all_data() |
主入口,获取全部数据 | (history, info, financials) |
数据类:
FetchConfig--- 获取参数(history_period, batch_size 等)StockInfo--- 股票基本信息(symbol, name, market_cap, total_share)
处理逻辑:
- 分批下载避免 API 限流
- 自动重试失败请求
- 列名标准化(yfinance 格式 → 统一格式)
feature_engine.py --- 技术指标计算
从原始 OHLCV 数据中计算约 80 个技术指标列。
指标分类:
移动平均与趋势
| 指标 | 说明 |
|---|---|
| ma5, ma10, ma20, ma60 | 简单移动平均线 |
| ret_1d, ret_5d, ret_20d | 收益率 |
| amplitude | 振幅 |
K 线形态识别(二值标志列,0/1)
单 K 形态:bull_candle, bear_candle, hammer, shooting_star, doji, dragonfly_doji, gravestone_doji
双 K 形态:bullish_engulfing, bearish_engulfing, inside_bar
三 K 形态:three_white_soldiers, three_black_crows
趋势形态:ma_bull, trend_confirm, pullback_hold, break_high_20, break_high_60, platform_breakout, false_breakout, double_bottom
量价形态:volume_breakout, volume_shrink_pullback
波动率形态:volatility_contraction, volatility_expansion
连续上涨:consec_up_3, consec_up_5
高级技术指标(连续值 + 信号标志)
MACD(移动平均收敛发散)
| 列名 | 类型 | 说明 |
|---|---|---|
| macd_dif | 连续值 | DIF 线(12日 EMA - 26日 EMA) |
| macd_dea | 连续值 | DEA 信号线(DIF 的 9日 EMA) |
| macd_hist | 连续值 | MACD 柱状图 = 2 × (DIF - DEA) |
| ind_macd_bull_cross | 标志 | 金叉(DIF 上穿 DEA) |
| ind_macd_bear_cross | 标志 | 死叉(DIF 下穿 DEA) |
| ind_macd_hist_positive | 标志 | 柱状图由负转正 |
RSI(相对强弱指数)
| 列名 | 类型 | 说明 |
|---|---|---|
| rsi_14 | 连续值 | 14日 RSI(Wilder 平滑) |
| ind_rsi_oversold | 标志 | RSI < 30(超卖) |
| ind_rsi_overbought | 标志 | RSI > 70(超买) |
| ind_rsi_bull_divergence | 标志 | 价格新低但 RSI 未新低(看涨背离) |
Bollinger Bands(布林带)
| 列名 | 类型 | 说明 |
|---|---|---|
| bb_upper | 连续值 | 上轨 = MA20 + 2 × 标准差 |
| bb_mid | 连续值 | 中轨 = 20日 SMA |
| bb_lower | 连续值 | 下轨 = MA20 - 2 × 标准差 |
| bb_width | 连续值 | 带宽百分比 = (上轨 - 下轨) / 中轨 × 100 |
| ind_bb_squeeze | 标志 | 带宽处于 20日最低值(即将突破) |
| ind_bb_upper_touch | 标志 | 价格触及或超过上轨 |
| ind_bb_lower_touch | 标志 | 价格触及或跌破下轨 |
VWAP(成交量加权平均价)
| 列名 | 类型 | 说明 |
|---|---|---|
| vwap | 连续值 | 当日成交量加权均价(日内累计,每个交易日重置) |
| ind_price_above_vwap | 标志 | 收盘价 > VWAP |
MFI(资金流量指数)
| 列名 | 类型 | 说明 |
|---|---|---|
| mfi_14 | 连续值 | 14日 MFI(带量的 RSI) |
| ind_mfi_oversold | 标志 | MFI < 20(超卖) |
| ind_mfi_overbought | 标志 | MFI > 80(超买) |
Williams %R(威廉指标)
| 列名 | 类型 | 说明 |
|---|---|---|
| willr_14 | 连续值 | 14日 Williams %R(范围 -100 ~ 0) |
| ind_willr_oversold | 标志 | Williams %R < -80(超卖) |
| ind_willr_overbought | 标志 | Williams %R > -20(超买) |
ADX(平均趋向指数)
| 列名 | 类型 | 说明 |
|---|---|---|
| adx_14 | 连续值 | 14日 ADX(趋势强度) |
| di_plus_14 | 连续值 | +DI(正向趋向指标) |
| di_minus_14 | 连续值 | -DI(负向趋向指标) |
| ind_adx_strong_trend | 标志 | ADX > 25(强趋势) |
| ind_di_bull_cross | 标志 | +DI 上穿 -DI |
CCI(商品通道指数)
| 列名 | 类型 | 说明 |
|---|---|---|
| cci_20 | 连续值 | 20日 CCI |
| ind_cci_oversold | 标志 | CCI < -100(超卖) |
| ind_cci_overbought | 标志 | CCI > 100(超买) |
Stochastic(随机指标)
| 列名 | 类型 | 说明 |
|---|---|---|
| stoch_k_14 | 连续值 | 14日 %K(快速) |
| stoch_d_14 | 连续值 | %K 的 3日 SMA(慢速) |
| ind_stoch_oversold | 标志 | %K < 20(超卖) |
| ind_stoch_overbought | 标志 | %K > 80(超买) |
| ind_stoch_bull_cross | 标志 | %K 上穿 %D(且 %K < 80) |
OBV(能量潮)
| 列名 | 类型 | 说明 |
|---|---|---|
| obv | 连续值 | 累计能量潮 |
| ind_obv_uptrend | 标志 | OBV > 5日前 OBV |
Chaikin Oscillator(佳庆振荡器)
| 列名 | 类型 | 说明 |
|---|---|---|
| chaikin_osc | 连续值 | A/D 线的 3日 EMA - 10日 EMA |
| ind_chaikin_bullish | 标志 | Chaikin 振荡器上穿零线 |
ATR(平均真实范围)
| 列名 | 类型 | 说明 |
|---|---|---|
| atr_14 | 连续值 | 14日 ATR(Wilder 平滑) |
| atr_stop_long | 连续值 | Chandelier 止损 = 周期最高价 - 3 × ATR |
成交量与波动率
| 指标 | 说明 |
|---|---|
| vol_ratio_5 | 5 日量比 |
| body_ratio | 实体比率 |
| upper/lower_shadow_ratio | 上下影线比率 |
| risk_ma20_dev, risk_ma60_dev | 均线偏离度 |
| risk_dd_20d | 20 日最大回撤 |
| risk_vol_20d | 20 日波动率 |
基本面评分指标
| 列名 | 类型 | 说明 |
|---|---|---|
| piotroski_score | 连续值 | Piotroski F-Score (0-9) |
| fund_piotroski_strong | 标志 | Piotroski ≥ 7(财务强健) |
| altman_z_score | 连续值 | Altman Z-Score(破产预警) |
| risk_financial_distress | 标志 | Altman Z < 1.81(财务困境) |
| value_quality_score | 连续值 | 价值-成长复合评分 (0-100) |
| fund_value_quality | 标志 | 复合评分 ≥ 70 |
核心函数:
add_features(df)--- 主入口,给历史 DataFrame 添加全部技术指标add_financial_features(df, metrics)--- 将财务指标合并到最新行(含 Piotroski 评分)
scorer.py --- 综合评分
计算每只股票的信号评分(0-100 分)和价值-成长复合评分。
信号评分组成:
| 维度 | 说明 | 分值范围 |
|---|---|---|
| 标志指标 | 多头信号加分,空头信号减分 | -20 ~ +50 |
| 连续指标 | 收益率、ROE、利润率等百分位排名 | 0 ~ +25 |
| PE 惩罚 | forward_pe 过高时扣分 | -10 ~ 0 |
关键权重:
| 信号 | 权重 |
|---|---|
| pattern_ma_bull | +15 |
| trend_confirm | +12 |
| break_high_60 | +10 |
| false_breakout | -8 |
| three_black_crows | -6 |
价值-成长复合评分 (compute_value_quality_score()):
| 维度 | 权重 | 排名方向 | 包含指标 |
|---|---|---|---|
| 估值质量 | 40% | 反向(低估值 = 高分) | forward_pe, price_to_book, peg_ratio, ps_ratio |
| 盈利能力 | 30% | 正向 | roe, roa, profit_margin, operating_margin |
| 成长性 | 30% | 正向 | revenue_growth, earnings_growth |
build_snapshot.py --- 快照编排器
协调数据获取 → 特征计算 → 基本面评分 → Altman Z-Score → 输出的完整流程。
核心函数:
| 函数 | 用途 |
|---|---|
build_snapshot() |
主入口,输出 parquet 文件 |
build_snapshot_dataframe() |
构建快照 DataFrame(每只股票一行) |
build_history_dataframe() |
构建历史 DataFrame(全部日期) |
_compute_altman_z(balance_sheet) |
计算 Altman Z-Score(破产预警) |
Altman Z-Score 公式:
Z = 1.2×X1 + 1.4×X2 + 3.3×X3 + 0.6×X4 + 1.0×X5
| 变量 | 定义 |
|---|---|
| X1 | 营运资本 / 总资产 |
| X2 | 留存收益 / 总资产 |
| X3 | EBIT / 总资产 |
| X4 | 市值 / 总负债 |
| X5 | 营收 / 总资产 |
Piotroski F-Score (在 add_financial_features() 中调用 _add_piotroski_score()):
9 项评分标准:
| # | 维度 | 条件 |
|---|---|---|
| 1 | 盈利能力 | ROA > 0 |
| 2 | 现金流 | 经营利润率 > 0(作为经营现金流代理) |
| 3 | ROA 改善 | 盈利增长 > 0 |
| 4 | 应计项目 | 经营利润率 > ROA |
| 5 | 杠杆 | 负债权益比 < 1.0 |
| 6 | 流动性 | 流动比率 > 1.5 |
| 7 | 股本稀释 | ROA > 0.05(代理) |
| 8 | 利润率 | 净利润率 > 0.15 |
| 9 | 营收增长 | 营收增长 > 0 |
输出文件:
data.parquet--- 最新交易日的快照(~200 行 × 80+ 列)history.parquet--- 全部历史技术指标数据
build_macro.py --- 宏观指标构建
获取宏观经济指标历史数据,输出 macro.parquet。
跟踪指标:
| Symbol | 指标 | 说明 |
|---|---|---|
| ^VIX | VIX 恐慌指数 | 市场波动率预期 |
| ^TNX | 10 年期美债收益率 | 无风险利率基准 |
| DX-Y.NYB | 美元指数 DXY | 美元强弱 |
| ^GSPC | 标普 500 指数 | 大盘基准 |
处理逻辑:
- 10Y 收益率自动转换为百分比格式
- 每个指标独立获取,单个失败不影响其他
- 输出格式:date, symbol, close, change_pct
build_sectors.py --- 板块数据构建
获取板块 ETF 和风格 ETF 的历史数据,输出 sectors.parquet。
11 个板块 ETF:XLK, XLF, XLV, XLE, XLI, XLY, XLU, XLRE, XLB, XLC, IBB
3 个风格 ETF:SPY(大盘基准), QQQ(科技基准), IWM(小盘基准)
输出格式:date, symbol, close, volume
signal_candidate_pool.py --- 信号候选池
离线多因子打分脚本,输出每日信号候选股 Top 20。
评分维度与权重:
| 维度 | 权重 | 包含因子 |
|---|---|---|
| 基本面 | 0.25 | 盈利增长、ROE、利润率、PE 惩罚 |
| 周线 | 0.20 | 20日动量、signal_score、MA 排列 |
| 日频 Alpha | 0.30 | signal_score、量能突破、突破信号 |
| 技术面 | 0.25 | ADX 趋势、MA 排列、风险指标 |
风险门控:
- 低流动性:20日日均成交额 < $5M → 标记
- 高波动率:20日波动率 > 4.0% → 标记
- 周线下跌趋势 → 标记
CLI 用法:
bash
python3 scripts/signal_candidate_pool.py \
--snapshot data.parquet \
--output tmp/signals/candidates.parquet \
--csv tmp/signals/candidates.csv
signal_outcomes.py --- 信号绩效计算
计算已入场信号的后验绩效指标。
产出指标:
| 指标 | 说明 |
|---|---|
| forward_return_1d | 1 日前向收益 |
| forward_return_3d | 3 日前向收益 |
| forward_return_5d | 5 日前向收益 |
| forward_return_10d | 10 日前向收益 |
| MFE | 最大有利偏移(Maximum Favorable Excursion) |
| MAE | 最大不利偏移(Maximum Adverse Excursion) |
| hit_stop | 是否触及止损 |
| hit_target | 是否触及目标价 |
CLI 用法:
bash
python3 scripts/signal_outcomes.py \
--db tmp/signals/signals.db \
--history history.parquet
rt_manager.py & rt_providers.py --- 实时数据
提供盘中实时数据的统一接口。
rt_providers.py 定义两种数据源:
| 数据源 | 延迟 | 排名 | 分钟 K 线 |
|---|---|---|---|
| YFinanceProvider(免费) | ~15 分钟 | 不支持 | 不支持 |
| AliyunProvider(付费) | 实时 | 支持 | 支持 |
rt_manager.py 提供缓存层:
- LRU 缓存(报价 200 条,K 线 50 条)
- 统一的异步 API 接口
rt_push_providers.py --- 实时推送源
可插拔的实时推送上游数据源架构,支持多种供应商。
支持的供应商:
| 供应商 | 协议 | 说明 |
|---|---|---|
| TickFlowProvider | HTTP 轮询 | 默认供应商,API Key 认证 |
| AshenProvider | WebSocket | 增量订阅,自动重连 |
| AliyunProvider | HTTP 轮询 | 阿里云金融 API |
特性:
- 统一的 Provider 接口(工厂模式)
- 可配置轮询间隔和推送频率
- 自动重连与退避策略
ashen_ws_client.py --- Ashen WebSocket 客户端
Ashen 实时行情服务的 WebSocket 客户端实现。
- 增量订阅管理(add/remove symbols)
- 自动重连(指数退避:1s → 2s → 5s → 10s)
- 心跳检测与超时处理
运行命令
bash
# 构建数据快照
python3 scripts/build_snapshot.py
# 构建宏观指标
python3 scripts/build_macro.py
# 构建板块数据
python3 scripts/build_sectors.py
# 生成信号候选池
python3 scripts/signal_candidate_pool.py --snapshot data.parquet --output tmp/signals/candidates.parquet
# 计算信号绩效
python3 scripts/signal_outcomes.py --db tmp/signals/signals.db --history history.parquet