通达信程序化下单(通用版)
用 Win32 消息/键盘事件驱动通达信原生的「闪电买入/卖出」下单框,完成真实委托提交。
复用通达信自己的券商通信、风控与委托号分配——脚本不碰网络协议、不碰资金密码,
提交后从确认框回执读合同号 / 券商拒绝原因做独立核实。
⚠️⚠️ 这是真实资金操作。所有脚本默认「预演」(不提交),只有显式给出
--commit --i-understand 两个参数才会真正下单。没有例外。
环境要求
| 项 | 要求 |
|---|---|
| 系统 | Windows(Win32 API,ctypes 标准库实现) |
| 软件 | 通达信交易客户端(各券商定制版均可,主窗口类名 TdxW_MainFrame_Class) |
| Python | 3.8+,仅标准库(无需 pip 安装任何东西;desktop.py 的截图功能可选装 Pillow) |
| 账户 | 用户已在通达信里登录交易账户 |
不需要:数据库、行情服务、券商接口密钥。证券规则(交易单位/涨跌停/价格精度)
由内置 scripts/_tdx_rules.py 按代码前缀离线判定。
脚本选择(先读这张表,选错=自动化"不完整")
| 脚本 | 点「买入/卖出」按钮 | 点「交易确认」对话框 | 用途 |
|---|---|---|---|
auto_order.py --commit |
✅ | ✅ 自带完整处理(等弹窗→读正文核对→点确认→支持多层) | 要全自动下单就用这个 |
fast_order.py --commit |
✅ | ✅ 逐段计时版(切标的→开窗→填单→提交→关回执) | 单笔快速链路 / 计时调试 |
batch_order.py |
✅ | ✅ | 一篮子批量(复用常开闪电窗,不切主窗) |
tdx_order_filler.py --commit |
✅ | ❌ 不含 | 只做填单/提交,弹窗会留在屏幕上等人点 |
🔴 踩过的坑:用 tdx_order_filler.py --commit 下单,结果每次「确定买入」都要用户手动点——
看起来像"自动化没做完整",其实是脚本选错了。全自动场景一律 auto_order.py。
Quick Start
# 预演(触发+填单+校验,走到确认框为止,不提交)
python scripts/auto_order.py --side buy --price 11.60 --qty 100 --code 600000
# 真实下单(必须同时给 --commit 和 --i-understand)
python scripts/auto_order.py --side buy --price 11.60 --qty 100 --code 600000 --commit --i-understand
# 卖出
python scripts/auto_order.py --side sell --price 11.60 --qty 100 --code 600000 --commit --i-understand
# 只读查看下单框当前值 / 确认框内容
python scripts/tdx_order_filler.py --show
python scripts/confirm_order.py
# 一篮子批量(先演练看每只确认框内容,再真提交)
python scripts/batch_order.py --basket "601398:1500:100,600000:95:200"
python scripts/batch_order.py --basket "601398:1500:100" --commit --i-understand
前置操作:运行前请把通达信主窗口最大化(脚本也会尝试最大化),
并确保主窗口停在个股/行情页面(不是交易登录框)。
完整链路(5 步,全部实测验证)
| 步 | 动作 | 实现要点 | 需前台 |
|---|---|---|---|
| 0 | 最大化主窗口 | ShowWindow(SW_MAXIMIZE) + 等 IsZoomed——否则下级窗口布局/按钮位置失准 |
— |
| 0.5 | 切到目标标的 | 主窗口敲 6 位代码 + 回车(下单窗口代码只读,标的完全由主窗口决定);回读标题校验 | ✅ |
| 1 | 打开闪电窗 | 买入 21 / 卖出 23 热键(必须连续投递 2,1,回车),等 #32770「闪电买入/卖出」窗口出现 |
✅ |
| 2 | 填价格/数量 | WM_SETTEXT 到 Edit id=12006(价格)/id=12007(数量),带重试回读 |
❌ |
| 3 | 点击买入/卖出 | BM_CLICK 到 Button id=1(不要用真鼠标坐标,会被遮挡/移动坑) |
❌ |
| 4 | 确认框 | 等「买入/卖出交易确认」#32770 → 读 id=7013 正文核对代码/价格/数量 → BM_CLICK id=7015「确认」 |
❌ |
| 5 | 回执核实 | 确认框正文/回执里读合同号或券商拒绝原因;关「提示」框 | ❌ |
关键控件 ID(实测)
闪电买入/卖出窗(class #32770):
12005 Edit 证券代码(只读,由主窗当前标的决定)
12006 Edit 价格 12007 Edit 数量
1 Button 「买 入 / 卖 出」 2 Button 取消
交易确认对话框(class #32770,标题含「交易确认」):
7013 Static 正文(代码/价格/数量/股东代码/最大可买)
7015 Button 「确认」 7016 Button 「取消」
跨进程读 Edit/Static 文本必须用 WM_GETTEXT(GetWindowTextW 对其它进程的 Edit
恒返回空——这是 Win32 行为,不是 bug)。
安全护栏(内置在脚本里,不可绕过)
G1 证券代码必须是 6 位且可解析
G2 数量为正且为「交易单位」整数倍 —— 内置 _tdx_rules.py:
科创板 688xxx → 200 股;其它股票/ETF → 100 股;可转债 11x/12x → 10 张
(转债按 100 算会下出 10 倍数量的废单;科创按 100 算会下出不足 200 股的废单)
G3 单笔金额 ≤ --max-amount(默认 500,000 元)
G4 真提交必须显式 --commit --i-understand
G5 确认框正文核对:代码/价格/数量三项与计划不符 → 点「取消」并报错
交易单位这个坑实测踩过:所有券商对可转债按「10 张整数倍」受理(沪深交易所 2022 新规统一口径),
按 A 股习惯乘以 100 会被券商整单拒绝。
🔴 模态框必须清场(最常见的"脚本卡死"根因)
「买入/卖出交易确认」和「提示」是交易核心模态框:
- 残留一个没关,通达信会吞掉所有
21/23热键(看起来像脚本卡死 5 秒+); - 更危险:残留确认框上误发 Enter/回车 = 可能直接真实下单;
- 真提交一单后闪电窗必被销毁(实测反复验证)⇒ 每笔都要重开窗,这是通达信硬设计,
不是脚本慢;未提交时(预演)窗口可连续复用。
fast_order.py 内置 close_leftover_dialogs():开窗前、下单返回前自动把残留模态框
只走 WM_CLOSE(=取消语义)清掉,绝不点 OK。如果你的自定义流程里出现"热键没反应",
先跑 python scripts/confirm_order.py 看是否有残留框,再考虑别的。
🔴 禁止裸发按键重试开窗——重试必须走脚本内的开窗函数(它带清场)。
🔴 账户归属:单子下给哪个账户,由通达信界面当前选中的账户决定
脚本改不了这个事实:除非软件主动切换账户,单子不会下错。
- 正确判据:读主窗右上角的账户下拉框(ComboBox
id=10025,CB_GETCURSEL+CB_GETLBTEXT;
GetWindowText对 ComboBox 返回空)。 - 第二道防线:确认框正文里有
股东代码:,可用fast_order.order(expect_shareholders=[...])
在提交前校验(多账户用户建议配置自己的股东代码清单)。 - ⚠️ 不要用「今日最新一笔委托的账户」反推当前账户——撤单/查询/历史记录都带旧账户,
「最新」≠「当前」(实测因此无辜拒单过)。
证券名称(可选增强,缺了不影响下单)
脚本会尝试向本机 127.0.0.1:8000 / 127.0.0.1 行情接口查证券名称用于切股校验;
没有这个接口时自动退化:按「标题非指数/板块页 + 非空」判定切股成功,
真正的安全由代码一致性与确认框正文核对保证。ETF/转债可能返回占位名「未知+代码」,
脚本已识别并降级处理,不会误判。
故障排查
| 症状 | 原因 → 处理 |
|---|---|
| 找不到主窗口 | 通达信没开,或该券商版主窗类名不是 TdxW_MainFrame_Class → 跑 probe_windows.py 枚举顶层窗口确认类名 |
21/23 热键无反应 |
①主窗停在指数/板块页(敲代码切个股再试)②有残留模态框 → close_leftover_dialogs / confirm_order.py 查看 |
| 主窗口不是目标股票 | 下单窗代码只读 → 先 select_stock(敲码+回车+标题校验),auto_order 已内置 |
| 确认框一直等不到 | 闪电窗按钮没点中 → 用 dump_controls.py 枚举控件 ID 核对 |
| 读回的文本是空 | 用了 GetWindowTextW → 必须用 WM_GETTEXT(脚本已内置正确实现) |
| 券商拒单(回执有错误码) | 常见:数量非单位整数倍(G2 应已拦截)、价格越界、可用资金/持仓不足——以回执文字为准 |
调试工具(只读/截图,不下单)
python scripts/probe_windows.py # 枚举顶层窗口(类名/标题/hwnd)
python scripts/dump_controls.py # 枚举某窗口全部子控件 ID
python scripts/confirm_order.py # 只读查看确认框内容(不点任何按钮)
python scripts/desktop.py shot --full --out=full.png # 截图(需 Pillow,可选)
红线(务必向用户复述后再执行 --commit)
- 真实资金:
--commit --i-understand一旦给出就是真下单,撤销需用户自己到客户端操作或用撤单功能。 - 不可卖空:卖出数量超过可用持仓会被券商拒绝(不会超卖,但会留废单)。
- 价格现取:脚本不会替用户猜价格——价格必须由用户/调用方明确给出。
- 先预演:新代码、新品种、新用户第一次跑,一律先不加
--commit演练一遍,看确认框内容对不对。 - 账户确认:多账户用户下单前确认通达信右上角选中的是目标账户。