QMT 策略 python代码写好了,怎么保护它(加密)。
一、为什么 QMT 策略代码需要加密
先看几个事实:
1. QMT 的源码就明晃晃躺在本地磁盘上。
你在策略编辑器里写的每一个字,都保存在 券商QMT版\python 目录下。虽然 QMT 默认模式下保存的文件用文本编辑器打开是乱码(磁盘上是密文),但只要你在策略编辑器里勾选了「启动本地 Python」或使用原生 Python 模式,源码就是明文。
2. pyc 不是加密,只是”格式转换”。
很多人以为把 .py 编译成 .pyc 就安全了。现实是:Python 3.8 以前的字节码,用 uncompyle6 一条命令就能近乎完美地还原出源码。也就是说,在 QMT 原生 Python 模式(固定 Python 3.6.8)下,pyc 等于裸奔。
3. 真实场景比想象中多。
- 和朋友、合作方共享策略跑实盘,代码放在别人机器上;
- 远程协作者、外包代写,代码多处流转。
只要代码离开你自己的机器,就需要考虑保护。
二、加密对运行速度的影响
先回答一个大家最关心的问题:加密会不会拖慢策略?
| 方案 | 速度影响 | 原因 |
|---|---|---|
| pyc | 几乎为零 | pyc 本来就是 Python 的字节码缓存格式,解释器执行路径完全相同 |
| QMT 官方加密 | 几乎为零 | 解密发生在策略加载阶段,运行时和明文无差别 |
| 混淆(PyArmor) | 轻微(1%~5%) | 运行时需要解壳和还原对象,函数调用有额外开销 |
| Cython 编译 pyd | 反而更快 | 机器码执行 + 可静态声明 C 类型,摆脱解释器开销 |
结论:加密的开销可以忽略,pyd 甚至是一项性能优化。对逐 K 线回调的 handlebar 场景来说,把核心计算用 Cython 类型化编译,实测能有明显提速——这和 Python 3.11 带来的解释器提速是叠加关系。
三、保护方法:从弱到强
Level 1:编译成 pyc
python -m compileall 或 QMT 运行后自带的缓存文件就是 pyc。
- Python ≤ 3.8:uncompyle6 / decompyle3 一键还原,等于没加密。
- Python ≥ 3.9:没有成熟的全自动反编译工具了,pycdc(Decompyle++)只能输出部分伪码,多数场景只能看字节码。
好消息是,大 QMT 的默认模式(不勾选原生 Python)现在支持 Python 3.12.10,在这个环境下 pyc 终于有了一点实际门槛。但要注意:dis 模块照样能反汇编,字符串常量(写死的账号、接口路径、参数字典)始终是明文。
定位:最低配防护,防随手抄袭,防不了有心人。如果用,把敏感字符串抽成外部配置文件。
Level 2:QMT 官方加密(推荐起步)
QMT 自带的加密通道,零成本:
- 加密公式:策略编辑器基本信息里勾选,加密后不输密码无法查看源代码;
- 凭密码导出公式:开启后连导出到本地都必须凭密码;
- 磁盘密文存储:默认模式下源文件本身就是密文,QMT 运行时自动在内存中解密;
- .rzrk 加密导出:策略文件以迅投特有的加密格式导出迁移,导入后保留密码和个性化设置。
实操上有一个重要原则:密码与策略包分离传递。包走网盘/文件传输,密码走私信或评论区回复,两者同时泄露才算泄露。
定位:官方原生、兼容性无忧、适合对外分发。缺点是信任边界仍在 QMT 本地——密文是随客户端一起解密运行的。
Level 3:代码混淆(PyArmor 等)
混淆工具会打乱变量名、加密字节码、加运行时解壳逻辑:
1 | pip install pyarmor |
混淆后代码逻辑不变但可读性极低,比 pyc 强一个档次。两个注意点:
- PyArmor 老版本存在公开的脱壳工具,新版本效果好很多;
- QMT 的 Python 环境有券商白名单机制,PyArmor 的运行时能否装载需要实测。
定位:需要把代码放到不完全可信的机器上运行时的中间方案,适合叠加在 Level 2 之上。
Level 4:Cython 编译成 pyd(本文重点,下一节展开)
字节码彻底消失,反编译问题变成逆向工程问题。强度接近商业软件保护,且速度更快。
四、pyd 方案详解
原理
.pyd 本质是一个 Windows DLL,只是命名约定不同(xxx.pyd 可被 import xxx 加载)。流程:
1 | 核心策略 algo.py |
关键差别:pyd 里没有 Python 字节码。uncompyle6、pycdc、dis 全部失效——反编译者面对的是 x64 机器码,只能上 IDA/Ghidra 做逆向工程,成本从”一条命令”变成”专业逆向工程师 + 数天工作量”。
环境要求(硬性)
| 项 | 要求 | 原因 |
|---|---|---|
| Python 版本 | 与 QMT 运行环境完全一致(默认模式 = 3.12.10,64 位) | pyd 绑定具体的 CPython ABI,cp312 的 pyd 在 3.6 里加载不了 |
| 编译器 | Visual Studio Build Tools(C++ 工作负载) | Cython 生成的是 C 代码,需要 cl.exe |
| 白名单 | pyd 基本自包含,一般不需要额外运行库;建议先问券商确认能加载自定义 .pyd | 券商白名单机制 |
注意:原生 Python 模式(3.6.8)下做 pyd 需要老版工具链,已经很难配——这是把核心算法放 3.12 默认模式的最好理由之一。
实操步骤
第 1 步:核心算法独立成模块(不放 init/handlebar 主文件里):
1 | # algo.py —— 核心信号逻辑 |
第 2 步:写编译脚本:
1 | # setup.py |
第 3 步:编译(在本机 Python 3.12.10 x64 环境执行):
1 | pip install cython setuptools |
产出 algo.cp312-win_amd64.pyd。务必保留 algo.py 原文件,移出 QMT 目录离线保存——pyd 无法还原回源码,丢了就真没了。
第 4 步:部署到 QMT。把 pyd 放进 QMT 的 Python 路径(bin.x64\python312 或策略目录)参考,主策略正常 import:
1 | # coding:gbk |
第 5 步:验证清单:
import algo成功,algo.__file__指向 pyd;- 删掉 algo.py 后策略仍能跑(确认没有残留源码);
- 修改算法 → 重新编译 → 验证新逻辑生效。QMT 默认模式有解释器状态残留,改完代码重启客户端最稳。
进阶:Cython 类型化,把”加密”做成”提速”
上面只是把 py 当 pyd 编译,已经是机器码了。但 Cython 真正的威力是静态类型声明。
cdef double 声明让循环里的运算直接走 C,配合 numpy 的 typed memoryview,核心计算部分可以有数倍提速。也就是说,pyd 方案的加密是”顺便的”,性能收益是”主要的”——这是它和混淆类方案本质的区别。详见另一篇关于 Cpython 提速的文章。
残余风险
- 机器码仍可逆向:IDA/Ghidra 能反汇编,字符串常量可见。敏感字符串可在 pyd 内做异或/运行时解码。
- 黑盒调用防不住:拿到 pyd 的人可以
import它直接调用你的函数——算法防”看”,不防”用”。需要绑定授权时,在 pyd 内加机器码指纹校验 + 时间锁。 - 依赖绑定:pyd 绑定 cp312。QMT 将来升 Python 3.13 要重新编译——所以必须保存 .py 源码。
- 跨机器分发:目标机的 QMT 必须也是相同 Python 小版本 + x64,MSVC 运行库齐全,否则加载报错。
五、场景速查
| 场景 | 建议组合 |
|---|---|
| 自己实盘 | pyd 核心模块 + 明文调度主策略 + 源码离线备份 |
| 对外发代码 | .rzrk 官方加密包 + 密码分离传递 + 代码脱敏 |
| 给合作方跑策略 | pyd 模块(加授权校验)+ 官方加密导出 |
| 3.12 默认模式随手保护 | pyc + 敏感字符串抽配置 |
六、总结
- pyc:3.6 下等于裸奔,3.12 下才有门槛,最低配;
- QMT 官方加密:零成本,对外分发的标准答案,记住密码与包分离;
- 混淆:中间方案,QMT 白名单环境要先实测;
- pyd:强度最高且速度更快,代价是要维护编译工具链;
- 最后记住一个原则:任何加密都防不住”愿意花功夫的人”,只能提高成本。核心策略留在自己机器上、只对外暴露最小的接口,永远比任何加密手段都干净。
免责声明:本文仅供技术学习与参考,不构成任何投资建议。文中涉及的代码片段仅演示思路,完整策略请在模拟环境中充分测试(实盘前必须模拟测试)后再考虑接入真实账户。量化交易涉及真实资金风险,据此操作盈亏自负。