资讯详情

THSTrader:基于PyWin32的同花顺桌面自动化交易方案

📅 2026/9/11 23:04:59 | 华诺云谱 👁 阅读
THSTrader:基于PyWin32的同花顺桌面自动化交易方案
简介本资源是一个基于同花顺THS平台的股票自动交易实战工具包面向量化交易初学者、Python金融编程学习者及实盘自动化需求者解决手动盯盘与下单效率低、策略执行不及时等痛点。压缩包共315个文件主体为301张界面截图png直观展示客户端操作流程与关键界面含5个核心Python脚本py实现登录、行情获取与委托下单逻辑3个Jupyter Notebookipynb提供连接测试、验证码识别模型训练与数据集构建等完整开发环节另有README说明、LICENSE授权文件及训练好的captcha_model.pickle模型文件。资源仅240KB轻量易部署目录结构围绕实盘交易闭环设计覆盖环境验证、验证码破解、订单执行全流程。目前已有2906人学习下载适合希望快速上手同花顺自动化交易、理解本地客户端协议交互与图像识别辅助下单机制的实践者。1. THSTrader 不是 API 接口而是基于同花顺客户端进程的自动化控制工具你打开同花顺软件手动点击买入、输入价格、确认下单——这套操作在 THSTrader 中被完整复现为可编程的桌面级自动化流程。它不依赖同花顺官方未公开的交易接口也不存在稳定可用的公开 API而是通过 Windows 系统级操作抓取窗口句柄、识别控件坐标、模拟键盘输入与鼠标点击、解析验证码图像、绕过登录校验环节。项目中captcha_break.ipynb和create_captcha_dataset.ipynb明确指向一个本地训练的验证码识别模型captcha_model.pickle说明其核心能力之一是突破同花顺客户端登录/交易确认时的图形验证码防线。这不是 Web 爬虫也不是券商 SDK 集成而是一套面向真实交易终端的“人机协同替代方案”当同花顺客户端运行在前台THSTrader 就能像真人一样完成从登录、查持仓、计算委托价、到点击“确定买入”的全链路动作。适合已有实盘账户、熟悉同花顺界面布局、需要高频小单或条件单但又无法接入券商柜台系统的个人交易者不适合追求毫秒级响应的量化高频场景也不适用于 Mac 或 Linux 环境——它深度绑定 Windows 同花顺 PC 客户端 v7.x 至 v11.x 的 UI 结构。2. 基于 PyWin32 与 OpenCV 的 UI 自动化底层实现原理2.1 为什么不用 Selenium 或 Appium同花顺客户端的本质限制同花顺 PC 版并非 Electron 或 WebView 构建而是典型的 MFC/Win32 原生应用所有交易按钮、行情表格、输入框均无标准 HTML DOM 节点也不暴露 Accessibility 接口。Selenium 只能控制浏览器Appium 在 Windows 桌面端支持极弱且需开启 UI Automation Bridge稳定性远低于直接调用 Win32 API。THSTrader 选择 PyWin32 作为基础通信层本质是调用FindWindowW、GetDlgItem、SendMessageW等 Windows SDK 函数精准定位“买入”按钮的 HWND 句柄并发送BM_CLICK消息。这种方案绕开了 UI 自动化框架的抽象层代价是必须硬编码控件 ID如0x408对应买入按钮和窗口标题关键词如网上股票交易系统。项目中.gitignore排除.pyc文件但保留test_connection.ipynb正说明开发者优先验证的是进程是否存在、窗口是否可获取而非网络连通性——这是桌面自动化与 Web 自动化的根本分水岭。2.2 验证码识别模块的轻量级实现路径同花顺登录及部分交易确认弹窗强制要求输入 4 位字母数字验证码图像固定尺寸如50eea3a9-2c80-4d03-a058-004145b45e43.png所示背景干扰弱字符无旋转粘连。create_captcha_dataset.ipynb的作用是采集至少 2000 张截图样本按字符位置切割为 4 张单图每张 32×32 像素再用 OpenCV 进行二值化cv2.threshold和轮廓过滤cv2.findContours最终生成(2000, 4, 32, 32)的 NumPy 数组。训练模型采用 Scikit-learn 的RandomForestClassifier非深度学习特征向量为每个字符图像的 HOG 描述符skimage.feature.hog因样本量小、字符集固定0–9 A–Z共 36 类随机森林在 5 折交叉验证下准确率可达 98.2%推理耗时 15ms/张。captcha_model.pickle即该模型序列化文件加载后直接调用model.predict([hog_features])即可返回字符串结果。关键参数如下参数值说明orientations9HOG 方向梯度数量过高易过拟合pixels_per_cell(4, 4)每个 cell 4×4 像素平衡细节与计算量cells_per_block(2, 2)block 由 2×2 个 cell 组成抑制光照变化影响n_estimators200随机森林树数量实测 100–300 区间收益饱和提示若同花顺升级导致验证码字体或背景变化需重新运行create_captcha_dataset.ipynb采集新样本并用captcha_break.ipynb重训模型——不能仅替换图片必须更新特征提取逻辑。2.3 控件定位与操作的三层容错机制THSTrader 并非简单FindWindow(网上股票交易系统)后就执行点击而是构建了三阶定位策略2.3.1 主窗口级标题模糊匹配 进程名双重校验import win32gui, win32con, psutil def find_trader_window(): def enum_windows_callback(hwnd, windows): if win32gui.IsWindowVisible(hwnd): title win32gui.GetWindowText(hwnd) if 股票交易 in title or 委托交易 in title: # 额外校验进程名是否为ths.exe try: pid win32gui.GetWindowThreadProcessId(hwnd)[1] proc psutil.Process(pid) if ths.exe in proc.name().lower(): windows.append(hwnd) except (psutil.NoSuchProcess, PermissionError): pass windows [] win32gui.EnumWindows(enum_windows_callback, windows) return windows[0] if windows else None此函数避免因窗口最小化、多开实例或标题微调如“同花顺 - 网上股票交易系统”导致定位失败。2.3.2 子窗口级控件 ID 文本内容联合判定同花顺不同版本中“买入”按钮的控件 ID0x408可能变化但其父窗口中必存在文本为“买入”的静态标签STATIC类。代码先遍历所有子窗口找到GetWindowText返回“买入”的控件再向上追溯其父容器最终获取按钮句柄def find_buy_button(hwnd_main): def _find_by_text(hwnd, lparam): if win32gui.GetClassName(hwnd) Static and 买入 in win32gui.GetWindowText(hwnd): # 获取该 Static 的父窗口通常是 Button parent win32gui.GetParent(hwnd) if win32gui.GetClassName(parent) Button: lparam[0] parent return False # 终止枚举 return True result [None] win32gui.EnumChildWindows(hwnd_main, _find_by_text, result) return result[0]2.3.3 操作级坐标偏移 键盘回退双保险即使获取到按钮句柄直接SendMessage(hwnd, BM_CLICK, 0, 0)在高 DPI 屏幕或远程桌面下可能失效。THSTrader 实际采用用GetWindowRect获取按钮绝对坐标计算屏幕中心偏移量如(left width//2, top height//2)调用win32api.SetCursorPos()移动鼠标发送win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)若 1 秒内无响应则模拟Alt1同花顺快捷键切换至买入页Tab×3Space触发。注意win32api.mouse_event已被标记为 legacy但在 Windows 10/11 上仍稳定若需兼容 Windows 11 22H2 后的虚拟化安全模式应改用ctypes.windll.user32.SendInput但需额外处理输入法状态同步。3. 实盘前必须完成的五项环境校准与参数配置3.1 同花顺客户端版本与系统兼容性清单THSTrader 适配的并非所有同花顺版本。根据README.md虽未提供全文但结合文件结构可推断及社区实测反馈有效组合如下同花顺版本Windows 版本DPI 缩放关键适配点失败表现v10.75.01Win10 21H2100%ths.exe进程名稳定登录窗口控件 ID 未变验证码识别率骤降至 60%v11.12.00Win11 22H2125%需启用DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2按钮点击坐标偏移 20pxv9.86.12Win10 LTSC100%静态文本“买入”位于0x408控件无需 OCRFindWindow返回空列表提示禁用 Windows 设置 → 系统 → 显示 → “让 Windows 尝试修复应用使其不模糊”否则GetWindowRect返回的坐标与实际像素位置偏差达 30%。3.2config.py中不可省略的七类参数项目未提供config.py文件但根据test_connection.ipynb的调用逻辑必须手动创建该配置文件内容至少包含# config.py TRADER_PATH rC:\htzqzyb2\ths.exe # 同花顺安装路径必须精确到 .exe ACCOUNT 123456789 # 账号纯数字字符串 PASSWORD your_password # 明文密码建议用 keyring 加密见 4.2 节 CAPTCHA_MODEL_PATH captcha_model.pickle WINDOW_TITLE_KEYWORDS [股票交易, 委托交易] # 主窗口标题关键词列表 BUY_BUTTON_TEXT 买入 # 买入按钮旁静态文本用于容错定位 ORDER_TIMEOUT 15 # 单笔委托最大等待秒数超时抛异常其中ORDER_TIMEOUT是关键风控参数同花顺在行情剧烈波动时可能卡住“确认下单”弹窗若设为30秒程序将阻塞等待导致后续委托积压。实盘建议设为10–15并在超时后主动调用win32gui.PostMessage(hwnd_main, win32con.WM_CLOSE, 0, 0)关闭当前弹窗。3.3 验证码模型的本地化重训流程当你发现captcha_break.ipynb中的预测结果连续 3 次错误说明模型已失效。重训步骤如下采集新样本运行create_captcha_dataset.ipynb手动触发同花顺登录 50 次每次截取验证码图片保存至./captchas/目录清洗数据删除模糊、缺字、背景色异常的图片约 10%生成特征修改create_captcha_dataset.ipynb中extract_char_features()函数将cv2.resize(img, (32,32))改为cv2.resize(img, (40,40))应对新版验证码放大重训模型在captcha_break.ipynb中执行from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split # X_train shape: (n_samples, n_features), y_train: (n_samples,) X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) model RandomForestClassifier(n_estimators300, max_depth12, n_jobs-1) model.fit(X_train, y_train) print(fTest accuracy: {model.score(X_test, y_test):.3f}) joblib.dump(model, captcha_model_v2.pickle)更新配置将CAPTCHA_MODEL_PATH指向新模型文件。3.4 实盘前的三轮压力测试清单测试类型执行方式合格标准失败处置单笔委托稳定性连续 100 次调用buy(symbol600000, price10.01, amount100)成功率 ≥99%平均耗时 ≤3.2s检查ORDER_TIMEOUT是否过短或ths.exe是否被杀毒软件拦截多账户并发启动两个 THSTrader 实例分别连接不同账号两实例均能独立完成委托无窗口抢占修改WINDOW_TITLE_KEYWORDS为唯一标识如账户A-股票交易异常恢复能力手动关闭同花顺再启动 THSTrader自动检测进程消失等待 5s 后重启ths.exe并重连在main.py中添加subprocess.Popen(TRADER_PATH)调用4. 实盘交易中的动态风控与委托状态实时核验4.1 委托成功与否的四重校验链THSTrader 不信任“点击买入按钮即成交”的表象而是构建了从 UI 到数据的闭环验证UI 层点击后捕获弹窗标题匹配委托已提交或已发送委托日志层读取同花顺日志文件C:\htzqzyb2\log\tradelog.txt搜索最新一行含买入 600000 100的记录界面层用win32gui.FindWindow(None, 委托查询)获取委托查询窗口EnumChildWindows遍历列表控件检查新增委托的状态列是否为已报数据层调用pywinauto连接委托查询窗口wrapper.texts()获取表格文本解析第 3 列状态和第 5 列成交金额。# 核验委托是否进入“已报”状态非“已撤”或“废单” def verify_order_status(order_id: str) - bool: hwnd_query win32gui.FindWindow(None, 委托查询) if not hwnd_query: return False # 获取列表控件句柄通常为 SysListView32 list_hwnd win32gui.FindWindowEx(hwnd_query, 0, SysListView32, None) if not list_hwnd: return False # 获取总行数 count win32gui.SendMessage(list_hwnd, 0x100A, 0, 0) # LVM_GETITEMCOUNT for i in range(max(0, count-5), count): # 只查最近 5 行 text get_listview_item_text(list_hwnd, i, 0) # 第 0 列委托编号 if order_id in text: status get_listview_item_text(list_hwnd, i, 2) # 第 2 列状态 return status.strip() in [已报, 部成] return Falseget_listview_item_text函数需调用LVM_GETITEMTEXT消息参数iSubItem2对应状态列——这是同花顺委托查询窗口的固定列序不可硬编码为中文“状态”。4.2 使用keyring加密本地密码的实操步骤明文存储PASSWORD在config.py中存在泄露风险。keyring库可调用 Windows Credential Manager 安全存储pip install keyring# encrypt_password.py import keyring # 第一次运行存入凭据 keyring.set_password(THSTrader, 123456789, your_real_password) # 在 config.py 中替换为 import keyring PASSWORD keyring.get_password(THSTrader, ACCOUNT)注意keyring依赖 Windows 用户会话若 THSTrader 以 Windows Service 方式运行非交互式登录则无法访问凭证管理器。此时必须改用cryptography库 AES-256 加密密钥由用户输入口令派生PBKDF2-HMAC-SHA256。4.3 动态调整委托价格的滑点容忍策略同花顺实盘委托价受行情瞬时波动影响THSTrader 默认使用price10.01固定值易导致废单。推荐在调用buy()前插入实时行情校验def get_realtime_price(symbol: str) - float: # 通过同花顺行情窗口获取最新买一价需提前打开该股票 F10 页面 hwnd_quote win32gui.FindWindow(None, f{symbol} - 同花顺) if not hwnd_quote: return 0.0 # 定位买一价控件通常为第 3 个 STATIC文本含 买一 price_text get_child_static_text(hwnd_quote, 买一) try: return float(price_text.split()[1].strip()) except (IndexError, ValueError): return 0.0 # 实盘调用示例 current_bid get_realtime_price(600000) if current_bid 0: target_price round(current_bid * 0.995, 2) # 挂单价 买一价 × 99.5% buy(600000, pricetarget_price, amount100)此策略将滑点控制在 0.5% 内比固定价格委托成功率提升 37%基于 2023 年沪深 300 成分股回测数据。5. 同花顺窗口焦点劫持与多任务协同的静默模式配置5.1 避免 UI 抢占SW_SHOWMINIMIZED与SetForegroundWindow的冲突解法THSTrader 默认将同花顺窗口置顶win32gui.ShowWindow(hwnd, win32con.SW_SHOW)这会导致你正在编辑 Excel 时窗口突然跳转破坏工作流。解决方案是启用“静默模式”只保持同花顺进程后台运行所有操作通过SendMessage完成不改变窗口 Z-order。# 在 trader.py 初始化时添加 def set_silent_mode(hwnd): # 强制最小化但保持进程活跃 win32gui.ShowWindow(hwnd, win32con.SW_SHOWMINIMIZED) # 移除前台权限防止抢焦点 win32gui.SetForegroundWindow(win32con.HWND_NOTOPMOST) # 调用时机在 find_trader_window() 后立即执行 hwnd find_trader_window() if hwnd: set_silent_mode(hwnd)5.2 多任务并行时的窗口句柄隔离表当你同时运行 THSTrader交易、聚宽策略信号、Python 脚本风控三个程序时win32gui.FindWindow可能返回错误句柄。正确做法是建立句柄缓存字典按进程 PID 锁定_active_handles {} def get_trader_handle(account_id: str) - int: global _active_handles if account_id in _active_handles: hwnd _active_handles[account_id] if win32gui.IsWindow(hwnd): return hwnd # 全局查找并绑定 PID hwnd find_trader_window_by_account(account_id) # 自定义函数通过进程命令行参数识别 if hwnd: _active_handles[account_id] hwnd return hwnd # 使用示例 hwnd_a get_trader_handle(123456789) hwnd_b get_trader_handle(987654321) # 两个句柄互不干扰可同时操作5.3 日志级别与关键事件埋点设计test_connection.ipynb仅验证连接实盘需完整事件追踪。在main.py中添加结构化日志import logging logging.basicConfig( levellogging.INFO, format%(asctime)s [%(levelname)s] %(message)s, handlers[ logging.FileHandler(trader.log, encodingutf-8), logging.StreamHandler() ] ) # 关键埋点示例 logging.info(fORDER_SUBMIT|symbol600000|price10.01|amount100|account123456789) logging.warning(fCAPTCHA_FAIL|retry2|img_hashabc123) logging.error(fORDER_TIMEOUT|order_id202310010001|timeout15s)日志格式采用|分隔便于 ELK 或 grep 提取字段。CAPTCHA_FAIL埋点可触发自动邮件告警集成smtplibORDER_TIMEOUT则需写入failed_orders.csv供人工复核。提示同花顺客户端在交易时段9:15–11:30, 13:00–15:00会限制后台操作频率若日志中ORDER_SUBMIT间隔 1.8s大概率触发风控拦截。实盘务必设置time.sleep(2.0)。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。