Python对接通达信实现股票自动化交易:行情、信号与下单全链路拆解
简介pyautotrade_tdx 是一套面向华泰证券通达信版的股票自动化交易脚本适合具备 Python 基础、希望用程序替代人工盯盘与手动下单的量化交易爱好者。它可同时监控 5 只股票按预设条件自动触发买卖单次下单耗时控制在 2 秒以内开发环境为 Win10 64 位搭配 Python3、pywin32 与 tushare32 位 Python3 同样可用。资源包共 12 个文件约 166KB以 8 张 png 界面截图、1 个 pyw 主程序、1 个 py 封装模块、1 份 license 与 1 份 md 说明为主截图直观展示对买对卖界面与参数设置主程序负责条件判断与下单封装模块则调用 Windows API 完成界面交互。使用前需先启动交易软件并停留在对买对卖界面时间条件满足后再校验价格条件股票数量按 100 的倍数取整。目前已有 3221 人学习配套 QQ 群可供交流排错适合想快速搭建自动化交易原型的读者参考。1. 股票自动化交易从手动盯盘到脚本托管中间隔着多少坑做股票自动化交易这件事很多人第一反应是「写个脚本自动下单」但真正落地时会发现下单只是最末端的一环。pyautotrade_tdx 这个方向核心思路是用 Python 对接通达信TDX的行情与交易接口把选股、信号计算、委托下单、持仓管理串成一条自动化的链路。它解决的不是「能不能买到」的问题而是「能不能在无人值守的情况下按既定策略稳定执行」的问题。适合两类人一是已经有明确交易策略、想摆脱手动执行延迟的量化爱好者二是想把通达信作为行情源和交易通道、用 Python 做策略中枢的开发者。前提是你得接受一个现实——自动化交易不是印钞机它只是把你的策略执行得更纪律化策略本身的盈亏逻辑不会因为自动化而改变。2. 拆解 pyautotrade_tdx行情、信号、下单三条链路怎么接2.1 为什么选通达信作为对接目标通达信在国内券商体系里覆盖面广大多数券商版客户端都基于它的内核这意味着你写的对接逻辑有较大概率能复用。常见做法是两条路一条是读取通达信本地数据文件日线、分钟线另一条是通过其行情接口或窗口消息机制获取实时数据。前者适合做历史回测和盘后选股后者适合盘中实时信号触发。我一般会先用本地数据文件跑通策略逻辑确认信号没问题再切到实时链路这样能把「策略错」和「对接错」两类问题分开排查。本地数据文件主要是.day格式的日线数据和.lc1/.lc5格式的分钟线数据存放在通达信安装目录的vipdoc文件夹下。读取这些文件不需要启动客户端适合做批量回测。import struct import os from datetime import datetime def read_tdx_day(filepath): 读取通达信 .day 日线文件 每条记录 32 字节日期(4) 开(4) 高(4) 低(4) 收(4) 成交额(4) 成交量(4) 保留(4) 价格单位是分需要除以 100 data [] with open(filepath, rb) as f: buf f.read() # 每条记录 32 字节循环解析 for i in range(0, len(buf), 32): record buf[i:i32] if len(record) 32: break # 日期是 YYYYMMDD 的整数 date_int struct.unpack(I, record[0:4])[0] open_p struct.unpack(I, record[4:8])[0] / 100.0 high_p struct.unpack(I, record[8:12])[0] / 100.0 low_p struct.unpack(I, record[12:16])[0] / 100.0 close_p struct.unpack(I, record[16:20])[0] / 100.0 amount struct.unpack(f, record[20:24])[0] volume struct.unpack(I, record[24:28])[0] data.append({ date: str(date_int), open: open_p, high: high_p, low: low_p, close: close_p, amount: amount, volume: volume }) return data # 使用示例读取某只股票的日线数据 # 路径规则vipdoc/sh/lday/sh600000.day 或 vipdoc/sz/lday/sz000001.day filepath rC:\new_tdx\vipdoc\sh\lday\sh600000.day if os.path.exists(filepath): bars read_tdx_day(filepath) print(f共读取 {len(bars)} 条日线数据) print(bars[-1]) # 打印最新一条这段代码的关键点在于字节序和单位。通达信.day文件用小端序价格字段是整数单位是分所以除以 100 才是元。成交额是浮点数成交量是整数股数。如果你读出来的价格明显偏大或偏小先检查是不是单位搞错了。日期字段直接是YYYYMMDD格式的整数不需要额外转换。2.2 信号计算把策略翻译成可执行的 Python 逻辑拿到行情数据后下一步是计算交易信号。这里最容易翻车的地方是「未来函数」——用了当天收盘后才能确定的数据去判断当天开盘该不该买。血泪经验是回测时信号漂亮得不行实盘一跑就亏多半是未来函数在作祟。一个常见的双均线策略信号逻辑应该是短期均线上穿长期均线时产生买入信号下穿时产生卖出信号。计算均线时只能用当前 bar 及之前的数据。import pandas as pd def compute_ma_signal(bars, short_window5, long_window20): 双均线信号计算 bars: read_tdx_day 返回的列表 short_window: 短均线周期 long_window: 长均线周期 返回带信号的 DataFrame df pd.DataFrame(bars) df[close] df[close].astype(float) # 计算均线min_periods 确保前期数据不足时不产生信号 df[ma_short] df[close].rolling(windowshort_window, min_periodsshort_window).mean() df[ma_long] df[close].rolling(windowlong_window, min_periodslong_window).mean() # 信号1 买入-1 卖出0 无操作 df[signal] 0 # 短均线上穿长均线 df.loc[(df[ma_short] df[ma_long]) (df[ma_short].shift(1) df[ma_long].shift(1)), signal] 1 # 短均线下穿长均线 df.loc[(df[ma_short] df[ma_long]) (df[ma_short].shift(1) df[ma_long].shift(1)), signal] -1 return df # 使用示例 # df compute_ma_signal(bars, short_window5, long_window20) # buy_days df[df[signal] 1] # print(f买入信号次数: {len(buy_days)})参数说明short_window和long_window是最核心的两个参数。短周期越小信号越灵敏但假信号越多长周期越大信号越稳定但滞后越明显。我一般会先用 5 和 20 跑一遍看看信号分布是否合理再根据标的波动特性调整。min_periods这个参数很多人会忽略如果不设前期均线会用不完整的数据计算导致前几根 bar 的信号不可靠。2.3 下单链路从信号到委托的最后一公里信号算出来之后怎么把委托发出去常见做法有三种一是通过券商提供的 API如果有二是通过通达信的窗口消息机制模拟人工操作三是通过第三方交易接口。第一种最稳定但门槛高第二种最通用但最脆弱第三种需要额外依赖。窗口消息机制的核心思路是找到通达信下单窗口的控件句柄填入股票代码、价格、数量然后模拟点击「买入」按钮。这种方式的问题在于通达信版本更新后控件布局可能变化导致脚本失效。所以我在写这类代码时会把控件查找逻辑封装成独立函数方便版本变化时快速定位修改。import win32gui import win32con import time def find_window_by_title(title_keyword): 根据标题关键词查找窗口句柄 result [] def callback(hwnd, _): if win32gui.IsWindowVisible(hwnd): text win32gui.GetWindowText(hwnd) if title_keyword in text: result.append((hwnd, text)) return True win32gui.EnumWindows(callback, None) return result def send_order_via_window(stock_code, price, volume, directionbuy): 通过窗口消息发送委托 注意这只是一个框架示例实际控件 ID 需要根据客户端版本调整 # 查找下单窗口 windows find_window_by_title(买入) if not windows: print(未找到下单窗口请确认客户端已打开) return False hwnd windows[0][0] # 这里需要根据实际控件结构填写代码、价格、数量的输入框句柄 # 通常需要用 EnumChildWindows 遍历子控件 # 填入股票代码 # win32gui.SendMessage(code_input_hwnd, win32con.WM_SETTEXT, 0, stock_code) # 填入价格 # win32gui.SendMessage(price_input_hwnd, win32con.WM_SETTEXT, 0, str(price)) # 填入数量 # win32gui.SendMessage(volume_input_hwnd, win32con.WM_SETTEXT, 0, str(volume)) # 点击买入按钮 # win32gui.SendMessage(button_hwnd, win32con.BM_CLICK, 0, 0) print(f委托已发送: {direction} {stock_code} 价格{price} 数量{volume}) return True这段代码的重点不是直接能用而是展示窗口消息机制的结构。实际使用时你需要用 Spy 或类似的工具找到目标控件的句柄和 ID。参数方面stock_code要带市场前缀如sh600000price要用委托价格不是市价volume要是 100 的整数倍。发送委托后一定要加延时并检查委托是否成功不能发完就不管了。3. 避坑指南自动化交易里那些让你半夜爬起来的事3.1 行情延迟导致的信号错位现象回测时信号在某个价格触发实盘时成交价差了好几个点。原因通常是行情数据有延迟或者你用的数据周期和信号计算周期不一致。解决方法是在信号计算和下单之间加一层校验确认当前行情时间戳和信号时间戳的差距在可接受范围内。如果差距过大宁可放弃这次信号也不要追。3.2 委托被拒但脚本以为成功了现象脚本显示已下单但实际持仓没变化。原因是窗口消息发送后没有检查返回结果或者委托被券商风控拦截了。解决方法是每次发送委托后主动查询委托列表或持仓列表确认委托状态。如果发现异常记录日志并触发告警。我一般会在脚本里加一个「委托确认」环节发送后等待 2 秒然后检查委托编号是否生成。3.3 客户端弹窗打断自动化流程现象脚本运行到一半卡住发现通达信弹了一个公告窗口或升级提示。原因是客户端的一些非交易弹窗抢占了焦点。解决方法是在脚本启动时先关闭所有非必要弹窗并在主循环里定期检查是否有新弹窗出现。可以用win32gui遍历窗口发现标题包含「公告」「提示」「升级」等关键词的窗口就自动关闭。3.4 资金计算错误导致超买现象脚本连续发出多笔买入委托导致可用资金不足部分委托被拒。原因是没有实时更新可用资金或者多线程同时下单时没有加锁。解决方法是在每次下单前重新查询可用资金并预留一定比例的安全垫。如果是多线程必须用锁保护下单逻辑。我一般会预留 5% 的资金作为缓冲避免因为手续费或价格波动导致资金不足。3.5 日志缺失导致问题无法回溯现象脚本跑了一周突然某天没执行但完全不知道发生了什么。原因是没有记录关键操作的日志。解决方法是至少记录以下几类日志——信号触发时间、委托发送时间、委托返回结果、持仓变化、异常堆栈。日志按天切分保留至少一个月。这样出问题时能快速定位是行情问题、信号问题还是下单问题。4. 把自动化交易跑稳的三个进阶习惯4.1 用模拟盘先跑通全链路很多人一上来就实盘结果因为一个小 bug 亏了钱。我的习惯是任何策略在实盘前先在模拟盘跑至少两周。模拟盘能暴露大部分对接问题比如委托格式错误、资金计算错误、弹窗干扰等。模拟盘跑稳了再切实盘实盘初期也只用小资金。4.2 给脚本加一个「急停开关」自动化交易最怕的是失控。我一般会在脚本里加一个文件监控如果某个特定文件存在脚本就暂停下单只记录信号。这样在发现异常时可以快速手动干预而不需要直接杀进程。急停开关的检查频率不用太高每轮循环检查一次即可。4.3 定期校验数据完整性通达信的本地数据文件偶尔会出现缺失或损坏导致信号计算错误。我一般会每周跑一次数据校验检查最近 N 天的数据是否有缺失价格是否有异常跳变。如果发现异常先重新下载数据再重新计算信号。这个习惯帮我避免了好几次因为数据问题导致的错误信号。校验项检查方法处理方式数据缺失对比交易日历检查是否有缺失日期重新下载对应日期的数据价格异常检查单日涨跌幅是否超过合理范围确认是否除权除息否则标记异常成交量异常检查成交量是否为 0 或异常放大确认是否停牌或数据错误均线断裂检查均线是否有突然跳变检查原始数据是否有跳变这三个习惯看起来简单但坚持下来能避开大部分低级错误。自动化交易的核心不是策略多复杂而是执行多稳定。希望帮到你。本文还有配套的精品资源点击获取