easytrader 远端服务模式实战:交易服务端与量化策略端分离部署指南
【免费下载链接】easytrader提供同花顺客户端/miniqmt/雪球的股票量化交易,支持跟踪 joinquant /ricequant 模拟交易 和 实盘雪球组合项目地址: https://gitcode.com/gh_mirrors/ea/easytrader
导读
本文讲解 easytrader 的远端服务模式(Remote Server Mode):将交易服务端与量化策略端部署在不同机器上,通过 HTTP 接口远程驱动券商客户端完成下单、查询等操作。读完本文,你将掌握如何在固定 IP 的云服务器上启动 easytrader 交易服务,如何用remoteclient在本地(或任意量化平台)远程调用买卖、撤单、查询资金持仓等全部交易能力,并理解底层 Flask 路由与请求参数的实现细节。
一、什么是远端服务模式
远端服务模式的核心思想是交易与策略分离。整个系统被拆成两个物理上独立的角色:
| 角色 | 部署位置 | 职责 |
|---|---|---|
| 交易服务端 | 通常是有固定IP地址的云服务器 | 运行easytrader交易服务,被动(或主动)接收交易信号,驱动交易软件完成实际下单 |
| 量化策略端 | JoinQuant、RiceQuant、Vn.Py等,物理上与交易服务端不在同一台电脑 | 运行量化策略,通过 HTTP 请求把交易指令发送给交易服务端 |
其中"交易软件"包括运行在交易服务端同一台机器上的下单软件(例如同花顺客户端xiadan.exe),也可以是运行在另一台服务器上的雪球xq账户。
这种分离模式的价值在于:量化策略往往运行在云端或本地的 Python 环境里(聚宽、米筐等平台),而券商交易客户端(如同花顺)通常依赖 Windows 桌面 GUI、受限于网络与安全策略,只能运行在特定的云服务器上。远端服务模式让两者各司其职,策略端只需通过 HTTP 即可驱动远端的交易客户端。
二、交易服务端:启动服务
交易服务端的启动代码非常简洁:
from easytrader import server server.run(port=1430) # 默认端口为 1430从源码 easytrader/server.py 可以看到,server.run内部基于 Flask 启动了一个监听在0.0.0.0的 Web 服务:
def run(port=1430): app.run(host="0.0.0.0", port=port)几点值得注意:
- 默认端口为
1430,可通过port参数自定义; - 服务监听
0.0.0.0,即对外网开放,因此必须结合云服务器安全组/防火墙规则做好访问控制,只允许可信来源访问; - 服务端通过
api.use(broker)创建券商交易对象,支持的 broker 类型与本地模式完全一致,见 easytrader/api.py:miniqmt:QMT 量化接口;xq/雪球:雪球组合;yh_client/银河客户端、ht_client/华泰客户端、wk_client/五矿客户端、htzq_client/海通证券客户端、gj_client/国金客户端、gf_client/广发客户端;universal_client/通用同花顺客户端、ths/同花顺客户端。
服务端 HTTP 接口一览
服务端启动后,会暴露一组 RESTful 风格的接口(见 easytrader/server.py):
| 方法 | 路径 | 说明 |
|---|---|---|
POST | /prepare | 初始化并登录券商客户端(body 中带broker字段),成功后返回{"msg": "login success"} |
GET | /balance | 获取资金状况 |
GET | /position | 获取持仓 |
GET | /auto_ipo | 一键打新 |
GET | /today_entrusts | 查询当日委托 |
GET | /today_trades | 查询当日成交 |
GET | /cancel_entrusts | 查询可撤委托 |
POST | /buy | 买入,body 携带security、price、amount |
POST | /sell | 卖出,body 携带security、price、amount |
POST | /cancel_entrust | 按委托号撤单,body 携带entrust_no |
GET | /exit | 退出客户端软件 |
其中/prepare的实现逻辑为:从 JSON body 中取出broker字段调用api.use(broker)创建交易对象,再将剩余参数透传给user.prepare(**json_data),最后把创建好的user保存在服务端的全局字典global_store中供后续请求复用(见 easytrader/server.py)。
所有接口都经过error_handle装饰器包装:一旦底层抛出异常,会返回400状态码以及{"error": "异常类名: 异常信息"}的 JSON 错误体(见 easytrader/server.py),方便远端定位问题。
三、量化策略端:调用服务
量化策略端无需安装任何券商客户端,只需要通过remoteclient创建一个远端用户对象即可调用服务:
from easytrader import remoteclient user = remoteclient.use( '使用客户端类型,可选 yh_client, ht_client, ths, xq等', host='服务器ip', port='服务器端口,默认为1430' ) user.buy(......) user.sell(......)remoteclient.use的签名定义在 easytrader/remoteclient.py:
def use(broker, host, port=1430, **kwargs): return RemoteClient(broker, host, port, **kwargs)RemoteClient在初始化时会做三件事(见 easytrader/remoteclient.py):
- 创建一个
requests.Session,用于复用 TCP 连接、保持 HTTP 基本认证状态; - 若传入了
user与passwd,则自动启用HTTPBasicAuth基本认证;若传入auth,则使用自定义的认证对象(对应服务端可配合 Flask 的认证中间件使用); - 拼接 API 基础地址:默认走
http://协议,若传入ssl=True则切换为https://(适用于反向代理强制走 HTTPS 的场景)。
因此完整的调用还可以这样写:
user = remoteclient.use( 'yh_client', host='123.45.67.89', port=1430, user='服务端HTTP认证用户名', # 可选 passwd='服务端HTTP认证密码', # 可选 ssl=False, # 可选,反向代理要求 HTTPS 时置为 True )四、登录准备:prepare
与本地模式一样,在交易之前需要先调用prepare完成客户端登录。远端模式下,prepare支持两种传参方式(见 easytrader/remoteclient.py):
方式一:直接传登录参数
user.prepare(user='账号', password='明文密码', exe_path=r'C:\htzqzyb2\xiadan.exe', comm_password='通讯密码(华泰)')方式二:传配置文件路径
user.prepare(config_path='/path/to/yh_client.json')传入config_path时,客户端会调用 easytrader/utils/misc.py 中的file2dict读取 JSON 配置,并自动把其中的user、password填充进请求参数。仓库根目录提供了现成的配置模板,例如 yh_client.json:
{ "user": "银河用户名", "password": "银河明文密码" }以及 gj_client.json:
{ "user": "国金用户名", "password": "国金明文密码" }无论哪种方式,prepare最终都会把broker类型一起打包,POST 到服务端的/prepare接口完成登录(见 easytrader/remoteclient.py)。
注意:服务端创建交易对象时使用的 broker 类型,由
remoteclient.use()的第一个参数决定;登录参数只是传给客户端完成认证,两者不要混淆。
五、远端交易操作与查询
登录成功后,远端用户对象提供了与本地用户完全一致的交易与查询 API,底层分别映射到服务端对应的 HTTP 接口(见 easytrader/remoteclient.py)。
5.1 买入与卖出
user.buy('162411', price=0.55, amount=100) # return {'entrust_no': 'xxxxxxxx'} user.sell('162411', price=0.55, amount=100) # return {'entrust_no': 'xxxxxxxx'}buy/sell会把security、price、amount三个参数 POST 到/buy、/sell接口(见 easytrader/remoteclient.py),因此远端下参数含义与本地完全一致:security为证券代码,price为委托价格,amount为委托数量。
5.2 撤单
user.cancel_entrust('buy/sell 获取的 entrust_no') # return {'message': 'success'}按委托号撤单,委托号来自买卖操作返回的entrust_no(见 easytrader/remoteclient.py)。
5.3 查询资金与持仓
user.balance # GET /balance,返回资金列表,字段如 '总资产'、'可用资金'、'参考市值' user.position # GET /position,返回持仓列表,字段如 '证券代码'、'证券名称'、'当前持仓'5.4 当日委托与当日成交
user.today_entrusts # GET /today_entrusts user.today_trades # GET /today_trades5.5 查询可撤委托与一键打新
user.cancel_entrusts # GET /cancel_entrusts,查询当日可撤委托 user.auto_ipo() # GET /auto_ipo,一键打新5.6 退出客户端
user.exit() # return {'msg': 'exit success'}上述返回字段的具体形态与本地模式一致,可参考 docs/usage.md 中给出的balance、position、today_entrusts、today_trades等真实返回示例,例如user.balance返回形如[{'总资产': 50136.21, '可用资金': 28494.21, ...}]的字典列表。
六、工作流程与调用链解析
一次完整的远端交易请求,其调用链可以概括为:
量化策略端 交易服务端(云服务器) ┌──────────────────┐ HTTP ┌──────────────────────────────┐ │ remoteclient.use │ ───────▶ │ Flask app (0.0.0.0:1430) │ │ user.prepare() │ /prepare│ api.use(broker) │ │ user.buy(...) │ /buy │ user.prepare(**json_data) │ │ user.sell(...) │ /sell │ global_store["user"] 复用 │ │ user.balance │ /balance│ user.buy(**json_data) │ └──────────────────┘ └──────────────────────────────┘关键设计细节:
- 单用户状态保存在服务端内存:
/prepare成功后,user对象被存入模块级字典global_store,之后的买卖、查询请求都直接复用该对象(见 easytrader/server.py)。因此一次服务进程内通常对应一个已登录的交易账户; - 错误以 JSON 形式回传:所有接口失败时返回
400状态码与{"error": ...},RemoteClient会检测status_code >= 300并抛出异常(见 easytrader/remoteclient.py); - 可扩展的协议:远端模式本质上只是把本地
Trader对象的属性和方法逐个暴露为 HTTP 接口,仓库测试 tests/test_easytrader.py 中验证的balance、today_entrusts、today_trades、cancel_entrust、buy、sell、auto_ipo等能力,在远端模式下均有对应接口,业务语义保持一致。
七、部署注意事项
结合 docs/install.md 中的云端部署建议,远端服务模式下需要注意以下几点:
- 交易客户端环境:若交易软件是 Windows 上的同花顺客户端(如
xiadan.exe),云服务器需具备图形界面运行环境;官方文档建议在云服务上部署时使用 TightVNC 等远程桌面工具(自带的远程桌面可能存在兼容问题); - 客户端设置:按 docs/install.md 的要求设置客户端——系统设置中将"界面不操作超时时间"设为 0,将默认买入/卖出价格、数量都置空,客户端不能最小化、不能处于精简模式,否则会导致下单价格出错或客户端超时锁定;
- 网络与安全:服务默认监听
0.0.0.0,建议通过云安全组限制来源 IP,或结合user/passwd参数启用 HTTP Basic Auth;若经过反向代理强制 HTTPS,可在remoteclient.use中传ssl=True; - 登录方式:部分券商专用同花顺客户端不支持自动登录,需要先手动登录客户端,再由服务端复用已登录窗口,此时
prepare的作用是让 easytrader 识别到已登录的窗口; - 验证码:若券商登录需要验证码,需在服务端单独安装
tesseract(注意不是pytesseract),保证命令行下tesseract可用;也可以手动登录后由 easytrader 直接识别已登录窗口。
八、最小可运行示例
综合以上内容,一个最小可运行的远端交易示例如下。
交易服务端(云服务器上运行):
from easytrader import server if __name__ == '__main__': server.run(port=1430) # 默认端口 1430,可自定义量化策略端(策略机上运行):
from easytrader import remoteclient # 1. 连接远端交易服务,指定券商类型 user = remoteclient.use('yh_client', host='服务器ip', port=1430) # 2. 登录交易客户端(方式一:直接传参) user.prepare(user='账号', password='明文密码') # 方式二:配置文件登录 # user.prepare(config_path='yh_client.json') # 3. 查询资金与持仓 print(user.balance) print(user.position) # 4. 交易 result = user.buy('162411', price=0.55, amount=100) print(result) user.sell('162411', price=0.55, amount=100) # 5. 撤单(使用买卖返回的委托号) user.cancel_entrust('xxxxxxxx')至此,量化策略端与交易客户端彻底解耦:策略逻辑可以运行在任意具备 Python 环境的机器上,而所有涉及券商客户端的敏感操作都被收敛在固定 IP 的交易服务端,这正是远端服务模式在 easytrader 生态中的核心价值所在。
【免费下载链接】easytrader提供同花顺客户端/miniqmt/雪球的股票量化交易,支持跟踪 joinquant /ricequant 模拟交易 和 实盘雪球组合项目地址: https://gitcode.com/gh_mirrors/ea/easytrader
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考