
简介面向量化交易与移动端自动化的Python开发者的“THSTrader”工具基于uiautomator2库和图色识别方法在同花顺手机版模拟炒股环境中实现自动登录、选股、买卖等操作为策略执行提供低成本的模拟盘验证渠道并预留扩展真实交易的改造余地。压缩包共9个文件约1.33MB包含主程序THSTrader.py、依赖清单requirements.txt、README说明、截图示例png/jpeg以及模拟器分辨率参考图等结构与代码设计便于快速上手和二次开发。目前已有203人学习下载适合初步接触量化交易、希望通过模拟盘验证Python策略逻辑的爱好者。借助这套工具开发者可以绕开券商接口和实盘资金门槛先在同花顺模拟环境中跑通全流程描述中同时提示了实盘化所需考虑的行情延迟、滑点、风控及合规等问题能帮助使用者提前建立量化交易的完整认知边界。 做量化交易的人十有八九都卡在同一个环节策略在回测里跑得风生水起一放到实盘就变脸。回测软件里没有行情延迟、没有盘中波动、没有滑点它只会冷冰冰地告诉你“这笔赚了”。这个项目说白了就是为了打通这个断层——用Python驱动同花顺手机版的模拟炒股功能通过uiautomator2控制App界面上的各种按钮和输入框同时用图色识别去读取行情、判断页面状态最终让策略在真实的行情数据和模拟撮合环境下自动跑起来。等这套流程验证稳定了换上券商App或者官方量化通道就能把同一套策略逻辑扩展到实盘。整套系统的价值在于同花顺没有开放官方Python API普通个人又申请不到低门槛的股票量化交易接口而模拟盘恰恰提供了一个足够真实的训练场。这个方案适合手里有成熟策略、想验证实盘可行性但暂时又不想把真金白银砸进去的人。下面我会按选型逻辑、代码骨架、实盘扩展、踩坑经验这几个维度展开尽量把每一步都讲透。1. 为什么要用手机模拟盘跑量化先解决实盘前的最后一公里1.1 回测再漂亮也替代不了模拟盘很多做策略的人容易陷入一个误区策略在历史数据上回测年化30%就觉得自己离财富自由不远了。实际上回测和真实交易之间隔着一道巨大的鸿沟。回测时你用的是当天的收盘价或者固定撮合价但真实盘口时刻在变化你的委托单要进入撮合队列要面对别人的挂单、大单砸盘、涨跌停封板这些都不是历史K线能完全模拟的。同花顺手机模拟炒股用真实行情驱动委托逻辑也尽量贴近真实交易规则股票涨停买不进就是买不进跌停卖不出就是卖不出。这恰好补上了回测和实盘之间缺的那段“临门一脚”。我见过太多策略回测时表现优秀丢进模拟盘跑两周就原形毕露原因就是回测模型太理想化没有充分考虑流动性和冲击成本。1.2 为什么选择同花顺而不是自建仿真环境股票量化圈常用的仿真方式各有各的短板。港股美股有完善的Paper Trading接口但A股这边长期缺少低门槛的官方模拟通道。用vn.py这类框架自己做仿真撮合行情数据源、手续费模型、涨跌停规则都得自己维护工作量不小而且撮合逻辑跟真实券商系统始终有差异。同花顺模拟盘的好处在于行情是真实的撮合规则是现成的涨跌停、停牌、ST风险提示都会真实触发。而且手机App端本身就是为散户设计的界面流程就是真实买卖的操作路径通过UI自动化去驱动它相当于把真实用户的操作过程脚本化这比自己做一套撮合引擎真实得多。再加上同花顺用户量大、版本更新稳定作为自动化目标比较靠谱。2. 技术选型拆解uiautomator2管手图色识别管眼2.1 uiautomator2Android自动化的实用选择Appium也能做Android界面自动化但它依赖Appium Server和WebDriver协议跑起来偏重部署也麻烦。uiautomator2则轻量得多它是基于Android官方UiAutomator框架封装的Python库安装后通过ADB与手机通信可以直接调用控件的click、swipe、text输入等操作API设计得很像人类操作手机的方式。实际使用中uiautomator2支持USB和WiFi两种连接方式。我建议调试阶段用USB连接稳定且传输速度快部署到长时间运行场景时再用WiFi连接并配合无线ADB避免USB松动导致断连。初始化代码很简单import uiautomator2 as u2 # 连接手机WiFi模式填手机IPUSB模式填serial号 d u2.connect(192.168.1.100) print(d.info)第一次运行uiautomator2会自动往手机上安装对应的ATX代理应用之后就可以通过Python控制手机了。整个体系已经非常成熟市面上很多手机群控工具都是基于它二次开发的稳定性经过了大规模验证。2.2 图色识别App里识别不到控件时的补充方案uiautomator2有一个天然的盲区同花顺App的很多页面元素是自绘的K线区域、分时图、部分自定义按钮根本不在系统控件树里。遇到这种情况uiautomator2拿到的是空控件列表你甚至找不到买入按钮在哪。这时候就必须让“眼睛”出场也就是图色识别。图色方法本质上是计算机视觉的落地应用核心逻辑就三步截屏、模板匹配或颜色判断、得到坐标后点击。比如你想点“买入”按钮先截一张屏然后把提前保存的“买入”按钮小图放进去做模板匹配找到最相似的位置import cv2 import numpy as np # 截取当前屏幕uiautomator2可以直接返回opencv格式图像 img d.screenshot(formatopencv) # 加载预先截好的按钮模板 tpl cv2.imread(buy_btn.png) res cv2.matchTemplate(img, tpl, cv2.TM_CCOEFF_NORMED) _, max_val, _, max_loc cv2.minMaxLoc(res) if max_val 0.85: # 相似度阈值低于这个值说明页面可能不对 x, y max_loc d.click(x tpl.shape[1] // 2, y tpl.shape[0] // 2) else: print(没有找到买入按钮当前页面可能异常)颜色判断在A股场景下尤其好用。A股红涨绿跌判断某只股票是涨是跌只需要把K线区域截出来统计像素颜色占比即可。这个方法比OCR识别数字快得多而且不需要训练模型。2.3 控件优先、图色兜底的分工逻辑在项目里我遵循一条原则能用控件解决就不用图色图色只在控件盲区出马。原因是控件点击带语义准确率高模板匹配容易受屏幕分辨率和主题影响同一张模板在深色模式和浅色模式下识别率可能差很多。实际操作时我会先dump一下当前界面的控件树看看目标元素是否存在# 打印当前界面的控件XML方便定位元素 print(d.dump_hierarchy())如果控件树里有“买入”文本节点直接d(text买入).click()就行如果控件树里一片空白再用截图模板匹配。这套策略既保证了操作速度又兼顾了覆盖率是几种方案里性价比最高的组合。3. 核心代码骨架策略信号如何变成模拟盘委托3.1 环境准备与权限配置先做基础准备工作。手机需要开启开发者选项和USB调试部分手机还需要关闭“USB安装应用”的二次确认弹窗。uiautomator2初始化时需要联网安装ATX代理所以手机要保持网络通畅。同花顺模拟盘需要在App里先开通模拟炒股账户获得模拟资金。不同版本的同花顺入口位置略有不同但一般都在“交易”或“首页”相关的频道里。跑自动化之前先把模拟账户开通好并确保登录状态不会过期。同花顺的包名以你手机里实际安装的为准常见的是com.hexin.plat.android可以通过在电脑上执行adb shell pm list packages | grep hexin来确认。3.2 行情读取截屏、裁剪、识别策略跑起来之后第一步是知道当前价格。同花顺自选股页面会直接显示最新价和涨跌幅我的处理方式是切换到自选股列表页整屏截图然后按预先记录的坐标区域裁剪出需要识别的部分再做数字识别。数字识别我没有上重度OCR模型而是用模板匹配做轻量识别。提前截好0到9的数字模板对裁剪区域做灰度化、二值化然后逐个匹配。这个方法在小范围固定字体场景下准确率很高而且识别速度在毫秒级import uiautomator2 as u2 import cv2 import numpy as np d u2.connect(192.168.1.100) # 截取当前屏幕 img d.screenshot(formatopencv) # 裁出价格区域坐标需要在真机上标定一次 price_region img[560:620, 300:480] gray cv2.cvtColor(price_region, cv2.COLOR_BGR2GRAY) _, thresh cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY) # 这里再做数字模板匹配返回识别出的价格字符串 # price match_digits(thresh)写策略代码时需要注意一点同花顺手机版界面会随版本更新微调机型不同坐标也不一样。建议把坐标、模板图片、按钮文字都抽成配置文件换机型或者升级App后只改配置不动代码逻辑。3.3 下单执行点击、输入、确认的完整链路下单是整个流程里风险最高的一步。模拟盘虽然亏的是虚拟资金但操作链路必须严谨因为这套代码以后是要搬到实盘环境验证的。基础的买入流程如下进入交易页、选择买入、输入股票代码、输入委托数量、点击买入按钮、确认委托。完整的下单函数大概长这样import time def buy(stock_code, amount): # 切换到交易Tab d(text交易).click() time.sleep(1) # 确保当前在买入页 if d(text买入).exists: d(text买入).click() time.sleep(0.5) # 输入股票代码 stock_input d(resourceIdcom.hexin.plat.android:id/stock_code) stock_input.clear_text() stock_input.send_keys(stock_code) time.sleep(0.5) # 输入委托数量 amount_input d(resourceIdcom.hexin.plat.android:id/amount) amount_input.clear_text() amount_input.send_keys(str(amount)) time.sleep(0.5) # 确认下单 if d(text买入).exists: d(text买入).click() time.sleep(1) # 二次确认弹窗 if d(text确认).exists: d(text确认).click() # 返回下单结果 result check_order_result() return result代码里的resourceId根据实际版本可能要调整但从流程上你就能看出UI自动化的核心是“每一步都必须确认上一步已经完成”。按键之间要留出足够的时间等待页面切换宁可慢一点也不要因为点击太快导致漏步骤。3.4 状态确认与异常处理下单之后不能直接走人必须确认委托是否进入队列、是否成交、是否被拒绝。我的做法是下单后进入“当日委托”页面读取委托状态如果状态是“已报”或“已成”说明链路正常如果状态是“废单”或“撤单”需要记录原因并暂停策略防止连续发送无效委托。异常处理是这套系统里最容易忽略的部分。手机App随时可能弹窗比如风险提示、广告弹窗、升级提醒这些都会挡住后续操作。我的兜底方案是维护一个“弹窗消除器”线程定期检查屏幕上是否出现“我知道了”“确定”“以后再说”这类通用按钮一旦发现就自动点击关闭。这听起来很朴素但实际能让整个系统的稳定性提升一个量级。4. 从模拟盘到实盘的扩展路径需要补的安全网4.1 模拟和实盘的本质区别模拟盘跑通了不代表实盘就能照搬。最大的差异是心理和资金安全上的模拟盘亏了不心疼实盘亏了会慌一慌就容易手动干预一干预整个自动化流程就乱了。技术层面还有三个实盘特有的问题实盘委托有真实手续费和滑点实盘下单速度要求更高特别是打板场景实盘账户有可用资金限制不能无限制加仓。所以在模拟盘阶段就要把实盘可能遇到的约束提前模拟进去。比如在自己代码里加上手续费模型每笔成交都扣除近似手续费再比如限制单笔下单金额模拟账户里有100万虚拟资金但单笔只允许用1万这样既验证了策略逻辑又提前适应了实盘的仓位管理节奏。4.2 实盘扩展开出的两条路第一条路是继续使用UI自动化驱动手机上的券商App完成真实下单。这条路兼容性最广几乎所有券商都有自己的手机App你的uiautomator2代码只需替换包名和控件ID就能适配。但需要特别提醒自动化交易必须使用自己名下的账户并且操作行为要遵守券商的服务协议和相关法律法规绝不能用于替他人操作或者任何违规场景。第二条路是切换券商官方量化终端。很多头部券商提供QMT、Ptrade这类量化交易终端支持Python策略直接对接柜台系统。这种方式的下单速度和稳定性远超UI自动化也更适合中高频策略。我建议把策略引擎和UI操作层做成解耦的两层结构策略层独立运行信号通过消息队列或文件传给执行层。这样先接UI操作层跑模拟盘再换官方API执行层上实盘改动量能做到最小。4.3 风控模块必须在模拟盘阶段就写进去实盘安全网里最核心的是风控模块。我自己在系统里写死了四条铁律单日最大亏损达到总资金的某个比例就停止交易单只股票持仓占比有上限所有委托单必须经过风控校验才能发送系统检测到连续三次操作异常时自动暂停并报警。这些风控逻辑在模拟盘阶段就可以完整跑起来。用模拟盘验证风控触发条件和阈值是否合理比上实盘之后才发现漏洞要安全得多。自动化交易的本质是让系统替你执行纪律但如果风控本身不健全执行得越坚决亏得越快。5. 调试过程中最值得记录的坑与调优经验5.1 手机连接稳定性无声无息断连最致命这个系统在长跑测试中遇到的最大问题是手机连接不稳定。WiFi ADB模式下手机屏幕熄灭一段时间后WiFi可能进入省电休眠ADB连接直接断开策略还在运行但执行层已经联系不上手机了结果就是整批信号没有执行持仓没有任何变化。解决方法是双管齐下一是设置手机开发者选项里的“不锁定屏幕”充电时保持常亮二是写一个看门狗脚本每隔30秒检查一次连接状态发现断线立即通过USB重新连接并恢复ATX服务。另外我换了多个安卓版本后发现关闭WiFi省电策略、给ATX应用开后台白名单都能显著降低断连概率。5.2 控件识别失败版本升级是最大的敌人同花顺App平均每个月都会更新一次升级后控件ID和布局经常会变。你今天用一个resourceId定位得好好的明天一更新就找不到了。更麻烦的是很多版本的弹窗控件ID是动态生成的每次都不一样靠resourceId根本无从下手。我的应对策略是尽量用稳定语义做定位比如用text属性定位按钮用相对路径定位特定区域。同时保留一套“降级方案”当某种定位方式连续失败三次就自动切换到图色识别。这套降级机制让我在App升级后通常只需要更新几个配置文件而不需要重写整个流程。5.3 图色识别精度模板数量决定成功率模板匹配看起来简单真正做起来细节不少。同一个买入按钮在亮色主题和暗色主题下外观完全不同在不同分辨率的手机上缩放比例也不同。只准备一套模板识别率可能只有60%到70%完全不够用。我后来把模板库做成了分组结构按主题色分组按屏幕分辨率分组启动时自动检测当前主题和分辨率选择对应模板组。识别时再叠加多个尺度扫描比如把输入图像分别缩放0.8、1.0、1.2倍后各匹配一次取最高相似度。这一通折腾下来识别率能稳定在95%以上误点率基本归零。5.4 下单速度与频率控制UI自动化的天然劣势是慢。一次完整下单流程从切换到交易页到最终确认怎么也要3到5秒这还不包括异常处理和重试。所以这方案适合日线级别、小时级别的中低频策略短线抢反弹那种秒级操作它扛不住也不该用它。我在策略引擎里加了下单频率限制单只股票两次下单之间至少间隔1分钟整体每分钟最多下3单。这样设置既有缓冲时间处理前一笔委托的确认又避免频繁操作触发App的风控机制。写在最后的实际体会整个项目从设计到跑稳我前前后后折腾了一个多月最深的体会是自动化交易工具真正的难点不在策略而在工程稳定性和执行细节。回测框架能让你快速验证想法但一个能在无人值守状态下连续运行一个月不出岔子的执行系统才是从量化爱好者走向实战的门槛。如果你也想照着这个方案做我的建议很直接先在模拟盘上连续跑至少一个月用实盘的节奏去审视策略和工具的稳定性把每一次异常都记录成日志。一个月后你回头看那些异常日志会发现大部分问题在模拟盘阶段暴露出来远远好过在实盘里用真金白银来交学费。最后再分享一个小技巧每天开盘前让系统自动检查一遍网络、资金、持仓和策略参数把检查结果发到你的微信或钉钉。这样人不在电脑前心里也始终有数。等你对这套系统的稳定性有了足够信心再考虑把执行层接到券商API上那时候你手里的就不只是一个模拟盘玩具而是一套经过实战验证的交易基础设施了。本文还有配套的精品资源点击获取