通达信策略Python量化选股框架:从公式复刻到多因子回测实战

发布时间:2026/9/30 1:21:07
通达信策略Python量化选股框架:从公式复刻到多因子回测实战
简介这份资源是一套基于通达信策略的Python量化选股框架面向具备一定Python基础、希望把通达信选股思路落地为可运行代码的量化投资者与策略研究者用于解决选股逻辑分散、难以批量回测与统一管理的问题。压缩包共111个文件约211KB以73个py源码文件为核心辅以13个pyc编译文件、8个sh脚本、4个xml与4个md说明文档另有txt、json、iml、example、template等配置与模板文件整体结构清晰便于按模块阅读与二次开发。内容涵盖数据管理、API配置、项目知识总结与更新说明等模块读者可据此理解选股框架的组织方式参考数据获取、策略编写与配置管理的实现思路并借助示例与模板快速搭建自己的量化选股流程。目前已有62人学习下载适合作为量化选股入门与框架搭建的实践参考。1. 拆开这个通达信策略 Python 量化选股框架我看到了什么很多人做量化选股卡在第一步不是策略本身而是数据从哪来、怎么把通达信里那套熟悉的指标逻辑搬到 Python 里跑。这个资源包给的就是一条现成的路子用 Python 搭一套量化选股框架把通达信策略的思路复刻进去形成可回测、可批量扫描、可输出选股结果的系统。它适合两类人——一类是手里有通达信指标源码、想批量验证选股效果的实战派另一类是想学 Python 量化交易、但不想从零造轮子的入门者。核心价值在于把「通达信公式」和「Python 选股引擎」这两件事接上了省掉大量数据清洗和框架搭建的重复劳动。2. 环境搭建与数据接入让 Python 先能读到行情2.1 为什么选 Python 而不是继续用通达信公式通达信公式语言TDX在盘中预警、副图指标上确实快但它有两个硬伤一是回测能力弱想跑十年历史数据验证一个选股逻辑公式语言几乎做不了二是无法做组合筛选比如「同时满足 RPS 强度 主力追踪 缠论买点」的多条件交集公式里写起来又长又难维护。Python 的优势正好补这两块——pandas 处理时间序列、numpy 做向量化计算、backtrader 或自建回测循环验证策略还能把选股结果直接写进 Excel 或数据库。这个框架的定位不是替代通达信而是把通达信里验证过的指标逻辑「翻译」成 Python 能跑的形式。常见做法是先在通达信里用副图指标确认信号形态再把公式里的核心条件比如均线排列、量比阈值、RPS 排名用 pandas 重写最后跑全市场扫描。2.2 环境配置Python 安装与依赖库新手最容易翻车的地方就是环境。我一般建议用 conda 建独立环境避免和系统 Python 打架。下面是可抄作业的步骤# 创建独立环境Python 版本建议 3.9 或 3.10兼容性最好 conda create -n tdx_quant python3.10 conda activate tdx_quant # 核心依赖数据处理 回测 行情接口 pip install pandas numpy matplotlib pip install akshare baostock # 免费行情数据源适合日线级选股 pip install openpyxl xlsxwriter # 选股结果写 Excel pip install tushare # 如有积分可用数据更全逻辑说明akshare 和 baostock 是两个不需要付费就能拿到 A 股日线数据的库适合做选股框架的数据底座。tushare 数据质量更高但需要积分按需选装。openpyxl 和 xlsxwriter 用于把每日选股结果导出成 Excel方便盘中对照通达信看盘。参数说明Python 版本不要选 3.12 以上部分量化库还没适配akshare 接口偶尔会因为数据源调整而失效建议同时装 baostock 做备份。2.3 行情数据获取与本地存储数据接入是选股框架的命脉。这个资源包的核心思路是「本地缓存 增量更新」避免每次选股都全量拉数据。import akshare as ak import pandas as pd import os from datetime import datetime, timedelta # 本地数据目录 DATA_DIR ./stock_data os.makedirs(DATA_DIR, exist_okTrue) def fetch_daily_data(symbol, start_date20200101): 获取单只股票日线数据带本地缓存 file_path os.path.join(DATA_DIR, f{symbol}.csv) # 如果本地已有数据只增量拉取最新部分 if os.path.exists(file_path): existing pd.read_csv(file_path, parse_dates[date]) last_date existing[date].max().strftime(%Y%m%d) # 从上次日期往后拉 new_data ak.stock_zh_a_hist( symbolsymbol, perioddaily, start_datelast_date, adjustqfq ) if not new_data.empty: combined pd.concat([existing, new_data]).drop_duplicates( subset[date], keeplast ) combined.to_csv(file_path, indexFalse) return combined return existing else: # 首次全量拉取 df ak.stock_zh_a_hist( symbolsymbol, perioddaily, start_datestart_date, adjustqfq ) df.to_csv(file_path, indexFalse) return df # 示例拉取单只股票 df fetch_daily_data(000001) print(df.tail())逻辑说明adjustqfq表示前复权量化选股必须用复权数据否则除权除息日会出现假信号。增量更新逻辑是先读本地 CSV 的最后日期只拉之后的数据再合并去重这样每天更新全市场 5000 只股票也就几分钟。参数说明start_date根据回测需求设定一般至少拉 3 年数据才有统计意义。symbol是 6 位代码akshare 的stock_zh_a_hist接口返回的列包括日期、开盘、收盘、最高、最低、成交量、成交额等够大部分选股因子用。注意akshare 接口有频率限制批量拉取时建议加time.sleep(0.3)否则容易被限流。全市场首次拉取建议分批次别一次性跑 5000 只。3. 通达信指标逻辑的 Python 复刻从公式到因子3.1 均线系统与 RPS 强度因子的实现通达信里最常见的选股条件就是均线多头排列和 RPS相对价格强度。RPS 的本质是个股在全体股票中的涨幅排名百分位通达信里用EXTDATA或自定义板块实现Python 里用 pandas 的rank一行搞定。import pandas as pd import numpy as np def calc_ma(df, periods[5, 10, 20, 60]): 计算多条均线 for p in periods: df[fma{p}] df[收盘].rolling(windowp).mean() return df def calc_rps(close_matrix, window20): 计算 RPS 相对强度 close_matrix: 列为股票代码行为日期的收盘价矩阵 window: 计算涨幅的周期默认 20 日 # 计算每只股票 window 日涨幅 returns close_matrix.pct_change(periodswindow) # 取最新一天的涨幅做百分位排名 latest_returns returns.iloc[-1] rps latest_returns.rank(pctTrue) * 100 return rps # 假设已有全市场收盘价矩阵 close_df # close_df pd.DataFrame(...) # index日期, columns股票代码 # rps_series calc_rps(close_df, window20) # strong_stocks rps_series[rps_series 90].index.tolist()逻辑说明pct_change(periodswindow)算的是 N 日涨幅rank(pctTrue)把涨幅转成 0 到 1 的百分位乘 100 就是 RPS 值。RPS 90 意味着这只股票在过去 20 天里涨幅排进全市场前 10%这是欧奈尔 CANSLIM 体系里的核心过滤条件。参数说明window一般取 20、50、120 三个周期分别算 RPS短周期抓爆发、长周期抓趋势。均线周期 5/10/20/60 是 A 股常用的组合60 日线常被当作中期趋势分水岭。3.2 量价配合与主力追踪信号的翻译通达信里「主力追踪」类副图指标核心逻辑通常是「放量突破 资金流入」。Python 里可以用成交额和价格变化的关系来近似。def volume_breakout(df, vol_ratio_threshold2.0, price_change_threshold0.03): 量价突破信号 vol_ratio_threshold: 量比阈值当日成交量 / 5日均量 price_change_threshold: 当日涨幅阈值 df[vol_ma5] df[成交量].rolling(5).mean() df[vol_ratio] df[成交量] / df[vol_ma5] df[pct_change] df[收盘].pct_change() # 放量 上涨 df[signal] ( (df[vol_ratio] vol_ratio_threshold) (df[pct_change] price_change_threshold) ) return df # 结合均线过滤只在 60 日线上方找信号 def filter_by_trend(df): df calc_ma(df, [60]) df[above_ma60] df[收盘] df[ma60] df[final_signal] df[signal] df[above_ma60] return df逻辑说明量比大于 2 意味着当日成交量是近期均量的两倍以上配合 3% 以上涨幅大概率是有资金在主动买入。再加一条「股价在 60 日线上方」的趋势过滤能过滤掉下跌途中的反弹假信号。参数说明vol_ratio_threshold设 2.0 是偏保守的激进策略可以降到 1.5price_change_threshold设 0.03 对应 3% 涨幅如果想抓首板可以调到 0.07 以上。这些参数没有绝对最优需要根据回测结果调。3.3 多因子组合与选股结果输出单因子选股噪音大实战里一般是多因子打分。这个框架的思路是每个因子给一个分数加权求和后取 Top N。def multi_factor_score(df, rps_value, ma_signal, vol_signal): 多因子打分 rps_value: RPS 值 0-100 ma_signal: 均线多头排列 bool vol_signal: 量价突破 bool score 0 score rps_value * 0.4 # RPS 权重 40% score 30 if ma_signal else 0 # 均线信号 30 分 score 30 if vol_signal else 0 # 量价信号 30 分 return score def export_selection(results, date_str): 导出选股结果到 Excel output_path f./selection_{date_str}.xlsx df pd.DataFrame(results) df df.sort_values(score, ascendingFalse) df.to_excel(output_path, indexFalse) print(f选股结果已导出{output_path}共 {len(df)} 只) return df逻辑说明RPS 是连续变量直接乘权重均线和量价是布尔信号满足给固定分。最终按总分排序取前 20 到 50 只作为候选池。导出 Excel 是为了方便盘中在通达信里对照看 K 线。参数说明权重分配可以调整比如更看重趋势就把均线信号权重提到 40。导出文件名带日期方便追溯每日选股结果。4. 避坑与常见问题排查4.1 数据复权没做对回测结果全是假的现象回测收益曲线漂亮得不像话实盘一跑就亏。原因用了不复权数据除权除息日价格跳空被当成真实涨跌。解决akshare 拉数据时强制adjustqfqbaostock 用adjustflag2前复权。所有价格类因子计算前先确认复权状态。4.2 未来函数用当天收盘价选股却假设当天开盘能买入现象选股信号当天涨停回测显示买入了但实盘根本买不进。原因用当日收盘数据算信号又假设当日能成交这是典型的未来函数。解决信号用 T 日收盘数据计算T1 日开盘或均价成交。回测时把买入价设为next_open别用close。4.3 akshare 接口突然报错或返回空数据现象昨天还能拉数据今天跑就报KeyError或返回空 DataFrame。原因akshare 底层爬的是公开数据源对方页面结构一变接口就失效。解决先pip install --upgrade akshare升级到最新版如果还不行换 baostock 做备份数据源。我一般会在代码里写双数据源切换逻辑一个挂了自动切另一个。4.4 全市场扫描太慢跑一次要半小时现象5000 只股票逐个拉数据、算因子效率极低。原因没用向量化循环里反复读文件。解决先把全市场收盘价和成交量拼成矩阵index 是日期columns 是股票代码因子计算全部用 pandas 向量化操作比逐只循环快几十倍。数据更新用增量别每次全量拉。4.5 选股结果和通达信里看到的不一致现象Python 选出来的股票在通达信里看副图指标并没有信号。原因通达信公式里可能用了未来函数、或者用了 Python 里没复刻的隐藏条件比如特定板块过滤、ST 剔除。解决逐条对照公式确认每个条件都翻译到位特别注意通达信里的REF、BACKSET这类函数BACKSET是典型未来函数Python 里不要用。5. 进阶技巧用参数扫描找到稳健的因子组合框架跑通之后真正决定收益的是参数。我一般不会手动一个个试而是写一个参数扫描循环把 RPS 周期、量比阈值、均线周期这几个核心参数做网格搜索看哪组参数在样本外表现最稳。import itertools def param_scan(close_matrix, volume_matrix, rps_windows, vol_thresholds): 参数网格扫描 返回每组参数对应的选股数量和后续 N 日平均收益 results [] for rps_w, vol_t in itertools.product(rps_windows, vol_thresholds): rps calc_rps(close_matrix, windowrps_w) selected rps[rps 90].index.tolist() # 统计选中股票后续 5 日平均收益 forward_returns [] for stock in selected: if stock in close_matrix.columns: prices close_matrix[stock].dropna() if len(prices) 5: ret prices.iloc[-1] / prices.iloc[-6] - 1 forward_returns.append(ret) avg_ret np.mean(forward_returns) if forward_returns else 0 results.append({ rps_window: rps_w, vol_threshold: vol_t, stock_count: len(selected), avg_forward_5d_return: round(avg_ret, 4) }) return pd.DataFrame(results).sort_values(avg_forward_5d_return, ascendingFalse) # 示例调用 # scan_result param_scan(close_df, vol_df, [10, 20, 50], [1.5, 2.0, 2.5]) # print(scan_result.head(10))逻辑说明itertools.product做笛卡尔积遍历所有参数组合。对每组参数先算 RPS 选出强势股再统计这些股票后续 5 日的平均收益。收益越高说明这组参数在历史上越有效。注意这只是样本内测试真正要验证还得留一段样本外数据。参数说明rps_windows建议覆盖 10 到 50 日太短噪音大、太长信号滞后。vol_thresholds从 1.5 到 2.5 足够再高选不出几只股票。扫描结果按平均收益排序但别只看收益最高的那组——还要看选股数量如果只选出 2 只股票收益再高也没有统计意义。我自己的习惯是参数扫描跑完后把排名前 20 的组合在样本外再跑一遍只保留样本内外表现一致的参数。那些样本内惊艳、样本外拉胯的组合基本都是过拟合实盘会教你做人。从那以后我每次调完参数都强制走一遍样本外验证再也不敢直接拿样本内最优参数上实盘。希望帮到你。本文还有配套的精品资源点击获取