前言
最怕的事之一,是本地调试脚本连上了实盘账户;或者 Git 里提交了带密码的配置,同事 clone 下来直接跑。我习惯把「环境(模拟/实盘)」和「密钥」都从代码里拆出去,用配置文件加环境变量,启动时打印当前模式,人为确认一眼再跑。
天勤TqSdk构造TqApi时传入TqSim、TqKq或TqAccount,改一行就能换环境,若写死在策略深处就容易改漏。下面给一套个人和小团队能落地的分离方式。
一、不要把密码写进仓库
禁止:
auth=TqAuth("真实账号","真实密码")# 提交到 Git应改为从环境变量或本地不提交的secrets.yaml读取:
importosfromtqsdkimportTqAuth user=os.environ["TQ_USER"]pwd=os.environ["TQ_PASSWORD"]auth=TqAuth(user,pwd)secrets.yaml加入.gitignore。CI 机器用密钥管理服务注入环境变量。
二、用配置区分 sim / kq / live
config.yaml示例(不含密码):
mode:sim# sim | kq | livesymbol:SHFE.rb2510启动脚本读取 mode,创建对应交易单元:
importosimportyamlfromtqsdkimportTqApi,TqAuth,TqSim,TqAccountdefload_cfg():withopen("config.yaml",encoding="utf-8")asf:returnyaml.safe_load(f)defcreate_api(cfg):auth=TqAuth(os.environ["TQ_USER"],os.environ["TQ_PASSWORD"])mode=cfg["mode"]ifmode=="sim":returnTqApi(TqSim(),auth=auth)ifmode=="kq":fromtqsdkimportTqKqreturnTqApi(TqKq(),auth=auth)ifmode=="live":returnTqApi(TqAccount("期货公司","资金账号","密码"),auth=auth)raiseValueError("unknown mode")cfg=load_cfg()print(">>> 当前模式:",cfg["mode"],"<<< 确认后 3 秒内继续")api=create_api(cfg)实盘模式前增加人工确认或二次环境变量ALLOW_LIVE=1,防止误点。
三、目录与路径分离
模拟日志、状态文件放data/sim/,实盘放data/live/,避免读错持久化状态(策略状态文件也应分目录存放)。云主机部署时用绝对路径环境变量TQ_DATA_DIR。
四、团队规范建议
| 项 | 做法 |
|---|---|
| 密钥 | 仅环境变量或密钥库 |
| 模式 | config.yaml 的 mode,启动打印 |
| 实盘 | 单独分支或单独启动脚本 |
| 代码评审 | 禁止合并含密码的 diff |
五、和 Jupyter、多脚本的关系
Notebook 里不要硬编码TqAccount;用同一create_api(cfg)入口。多个策略文件import同一配置模块,避免某文件漏改仍连实盘。
总结
模拟误连实盘,多数是配置和密钥没分离。天勤切换环境靠构造参数,策略层应集中创建TqApi,用 mode + 环境变量双保险,启动时显性打印当前模式。
建议今天就把仓库里的明文密码清掉、轮换一次快期密码,并加上config.example.yaml供同事复制。
FAQ
1)config.yaml 能放账号吗?
最好不要;只放 mode、合约等非敏感项。
2)Docker 怎么注入?
docker run -e TQ_USER=... -e TQ_PASSWORD=...
3)多账户?
多个环境变量前缀,如TQ_USER_A。
4)误连后如何自查?
查启动日志 mode、查api._account类型(调试用),对照客户端成交。
风险提示
本文用于工程安全实践,不构成投资建议。实盘操作务必双人复核或权限隔离。