QMT 策略代码保护指南(加密):从 pyc 到 pyd,加密等级从低到高怎么选

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 自带的加密通道,零成本:

  1. 加密公式:策略编辑器基本信息里勾选,加密后不输密码无法查看源代码;
  2. 凭密码导出公式:开启后连导出到本地都必须凭密码;
  3. 磁盘密文存储:默认模式下源文件本身就是密文,QMT 运行时自动在内存中解密;
  4. .rzrk 加密导出:策略文件以迅投特有的加密格式导出迁移,导入后保留密码和个性化设置。

实操上有一个重要原则:密码与策略包分离传递。包走网盘/文件传输,密码走私信或评论区回复,两者同时泄露才算泄露。

定位:官方原生、兼容性无忧、适合对外分发。缺点是信任边界仍在 QMT 本地——密文是随客户端一起解密运行的。

Level 3:代码混淆(PyArmor 等)

混淆工具会打乱变量名、加密字节码、加运行时解壳逻辑:

1
2
pip install pyarmor
pyarmor gen algo.py

混淆后代码逻辑不变但可读性极低,比 pyc 强一个档次。两个注意点:

  • PyArmor 老版本存在公开的脱壳工具,新版本效果好很多;
  • QMT 的 Python 环境有券商白名单机制,PyArmor 的运行时能否装载需要实测。

定位:需要把代码放到不完全可信的机器上运行时的中间方案,适合叠加在 Level 2 之上。

Level 4:Cython 编译成 pyd(本文重点,下一节展开)

字节码彻底消失,反编译问题变成逆向工程问题。强度接近商业软件保护,且速度更快。

四、pyd 方案详解

原理

.pyd 本质是一个 Windows DLL,只是命名约定不同(xxx.pyd 可被 import xxx 加载)。流程:

1
2
3
4
核心策略 algo.py
→ Cython 翻译成 C 代码(algo.c)
→ MSVC 编译成机器码(algo.cp312-win_amd64.pyd)
→ QMT 里 import 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
2
3
4
5
6
7
8
9
10
11
# algo.py —— 核心信号逻辑
def calc_signal(closes, fast=5, slow=20):
if len(closes) < slow:
return 0
ma_fast = sum(closes[-fast:]) / fast
ma_slow = sum(closes[-slow:]) / slow
if ma_fast > ma_slow:
return 1
elif ma_fast < ma_slow:
return -1
return 0

第 2 步:写编译脚本:

1
2
3
4
5
6
7
8
9
10
11
# setup.py
from setuptools import setup
from Cython.Build import cythonize

setup(
ext_modules=cythonize(
["algo.py"],
compiler_directives={"language_level": "3"},
nthreads=4,
)
)

第 3 步:编译(在本机 Python 3.12.10 x64 环境执行):

1
2
pip install cython setuptools
python setup.py build_ext --inplace

产出 algo.cp312-win_amd64.pyd。务必保留 algo.py 原文件,移出 QMT 目录离线保存——pyd 无法还原回源码,丢了就真没了。

第 4 步:部署到 QMT。把 pyd 放进 QMT 的 Python 路径(bin.x64\python312 或策略目录)参考,主策略正常 import:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# coding:gbk

"""主策略:明文,只做调度;核心算法在 pyd 里"""

account = "test"

import algo

def init(ContextInfo):
ContextInfo.signal = 0

def handlebar(ContextInfo):
if not ContextInfo.is_last_bar():
return
# 取行情后调用 pyd 里的核心算法
# sig = algo.calc_signal(closes)
...

第 5 步:验证清单:

  • import algo 成功,algo.__file__ 指向 pyd;
  • 删掉 algo.py 后策略仍能跑(确认没有残留源码);
  • 修改算法 → 重新编译 → 验证新逻辑生效。QMT 默认模式有解释器状态残留,改完代码重启客户端最稳。

进阶:Cython 类型化,把”加密”做成”提速”

上面只是把 py 当 pyd 编译,已经是机器码了。但 Cython 真正的威力是静态类型声明。

cdef double 声明让循环里的运算直接走 C,配合 numpy 的 typed memoryview,核心计算部分可以有数倍提速。也就是说,pyd 方案的加密是”顺便的”,性能收益是”主要的”——这是它和混淆类方案本质的区别。详见另一篇关于 Cpython 提速的文章。

残余风险

  1. 机器码仍可逆向:IDA/Ghidra 能反汇编,字符串常量可见。敏感字符串可在 pyd 内做异或/运行时解码。
  2. 黑盒调用防不住:拿到 pyd 的人可以 import 它直接调用你的函数——算法防”看”,不防”用”。需要绑定授权时,在 pyd 内加机器码指纹校验 + 时间锁。
  3. 依赖绑定:pyd 绑定 cp312。QMT 将来升 Python 3.13 要重新编译——所以必须保存 .py 源码。
  4. 跨机器分发:目标机的 QMT 必须也是相同 Python 小版本 + x64,MSVC 运行库齐全,否则加载报错。

五、场景速查

场景 建议组合
自己实盘 pyd 核心模块 + 明文调度主策略 + 源码离线备份
对外发代码 .rzrk 官方加密包 + 密码分离传递 + 代码脱敏
给合作方跑策略 pyd 模块(加授权校验)+ 官方加密导出
3.12 默认模式随手保护 pyc + 敏感字符串抽配置

六、总结

  • pyc:3.6 下等于裸奔,3.12 下才有门槛,最低配;
  • QMT 官方加密:零成本,对外分发的标准答案,记住密码与包分离;
  • 混淆:中间方案,QMT 白名单环境要先实测;
  • pyd:强度最高且速度更快,代价是要维护编译工具链;
  • 最后记住一个原则:任何加密都防不住”愿意花功夫的人”,只能提高成本。核心策略留在自己机器上、只对外暴露最小的接口,永远比任何加密手段都干净。

免责声明:本文仅供技术学习与参考,不构成任何投资建议。文中涉及的代码片段仅演示思路,完整策略请在模拟环境中充分测试(实盘前必须模拟测试)后再考虑接入真实账户。量化交易涉及真实资金风险,据此操作盈亏自负。


赞赏作者

赞赏码

本页面赞赏完全自愿,属于读者无偿鼓励,不提供任何商品、服务、答疑、内容解锁等对价。您可随意选择是否赞赏以及赞赏金额。

微信二维码 Share