本节摘要:QuantDinger 内置六家加密交易所的实盘适配器(官方 README 口径):Binance、OKX、Bitget、Bybit、Gate、HTX。本节先讲统一适配层的职责边界——它把行情、下单、账户查询抽象成统一接口,把各家差异吸收在适配器内部,但精度档位、最小下单量、费率档位这类"参数级差异"仍要逐所核对;然后是本节的重头戏:API key 权限最小化的完整清单——只开交易权限、禁用提币、绑定 IP 白名单、一用途一 key、定期轮换;接着给出测试网先行的验证清单与从测试网切到主网的门槛;最后用一份配置示例把接入动作固化。原则只有一条:权限上宁可少开再补,不可多开再收。
六家交易所的 REST 与 WebSocket 接口、字段命名、错误码体系各不相同。适配层(官方 README 口径支持上述六家)在上层策略与各家接口之间做翻译:
统一适配层的位置 策略(Strategy API V2) ──▶ trading-worker ──▶ 统一订单接口 │ ┌──────────┬──────────┬──────────┬────┴─────┬──────────┐ ▼ ▼ ▼ ▼ ▼ ▼ Binance OKX Bitget Bybit Gate HTX 适配器 适配器 适配器 适配器 适配器 适配器 (各家接口、错误码、限频规则被吸收在适配器内部)
它抹平的:接口协议、字段口径、订单状态机、基础限频处理。它抹不平的(策略层与配置层自己负责):
| 参数级差异 | 为什么要核对 |
|---|---|
| 价格/数量精度档位 | 精度不符的下单直接被拒 |
| 最小下单量与步长 | 小资金策略可能根本无法开仓 |
| 费率档位与 VIP 折扣 | 6.1 的回测费率要与之对齐 |
| 特殊交易规则 | 个别交易对的状态与限制随时可能变化 |
接入每一家时,先用第 07 章的可执行性检查把这张表过一遍——精度与最小量这类约束,适配器会校验并拒绝,但"能通过校验"和"适合你的资金规模"是两回事。
参数级核对也可以脚本化。下单前在 sizing 侧先按交易所公布的精度档位自行取齐一遍(示意逻辑,精度档位以各所官方文档为准):
# check_order_params.py —— 下单参数按精度档位取齐与下限校验(示意,档位以交易所官方为准) from decimal import Decimal, ROUND_DOWN def align_order(price, qty, spec): """spec 形如 {"tick": "0.01", "step": "0.001", "min_qty": "0.001", "min_notional": "5"}""" tick, step = Decimal(spec["tick"]), Decimal(spec["step"]) px = Decimal(str(price)).quantize(tick, rounding=ROUND_DOWN) # 价格按 tick 向下取齐 qx = Decimal(str(qty)).quantize(step, rounding=ROUND_DOWN) # 数量按 step 向下取齐 problems = [] if qx < Decimal(spec["min_qty"]): problems.append("低于最小下单量") if px * qx < Decimal(spec["min_notional"]): problems.append("低于最小成交额") return {"price": str(px), "qty": str(qx), "ok": not problems, "problems": problems}
两个讲法。其一,取齐方向选向下:向上取齐可能越过档位边界被拒,向下取齐最坏只是少买一点点。其二,这段代码不是替代适配器的校验,而是把参数级差异从"运行时报错"提前到"策略设计期发现"——如果回测的 sizing 天天产出 0.00347 这样的数量,问题应该在回测配置里就暴露,而不是等实盘适配器拒单三次、告警两条之后才发现。用 Decimal 而不是浮点,是因为精度取齐本身就是二进制浮点最不擅长的运算。
API key 泄露是自托管交易系统的第一大真实风险。最小化原则:key 的权限集合,恰好覆盖系统需要做的事,一项不多。逐项执行:
| 序 | 措施 | 做法 | 理由 |
|---|---|---|---|
| 1 | 只开交易权限 | 创建 key 时仅勾选读+交易 | 系统永不需要通过 API 转走资产 |
| 2 | 禁用提币权限 | 确认提币权限关闭,且不在任何场景打开 | 泄露时的最大损失边界 |
| 3 | 绑定 IP 白名单 | 只允许服务器出口 IP 访问 | key 被复制到他处也无法使用 |
| 4 | 一用途一 key | 回测拉数据、实盘下单各用独立 key | 单点泄露影响面可控,审计可区分 |
| 5 | 定期轮换 | 按固定周期(例如每季度,示意建议)换 key | 缩短潜在泄露的存活期 |
| 6 | 环境变量存放 | key 不进代码库、不进配置文件明文 | 版本历史是泄露的重灾区 |
第 6 项展开一句:QuantDinger 的密钥管理方式以官方文档为准,但"密钥最终落在哪个文件、这个文件是否被备份与同步到了别处"是你的责任,接入前应当亲自确认一遍存放路径与权限。
这六条与《Harness 工程:从零打造智能体运行环境》第 05 章《权限与审批门》里"给智能体的凭证永远只给最小集"是同一条纪律在交易场景的落地:你不会把保险柜钥匙连同密码一起交给信使,也不该给出金权限随交易 key。
六家交易所普遍提供测试网(testnet)环境,名称与申请方式以各家官方文档为准。切主网前,在测试网完成:
| 序 | 验证项 | 期望结果 |
|---|---|---|
| 1 | key 权限核验 | 测试网 key 同样只开交易权限 |
| 2 | 连通与限频 | 行情订阅与下单接口稳定,无限频报错 |
| 3 | 下单链路 | 市价单、限价单、撤单各走通一轮 |
| 4 | 精度与最小量 | 用目标资金规模的实际数量下单成功 |
| 5 | 错误处理 | 故意触发余额不足、精度错误,确认系统行为 |
| 6 | 对账预演 | 第 8.3 节的对账脚本在测试网数据上跑通 |
| 7 | 应急开关 | 第 10 章的一键停单在测试网实际按一次 |
第 5 项容易被跳过,但它最重要:错误的形态(错误码、字段、重试是否安全)决定了实盘第一次撞上它时系统是优雅降级还是连环重试。第 7 项把"出事时来不来得及"提前变成肌肉记忆。
(示意结构,字段名与适配器名称以官方文档为准。)
# exchange_binance.yaml —— 交易所接入配置(示意,字段以官方文档为准) exchange: name: binance environment: testnet # testnet | mainnet,切换必须走审批 credentials_env: QD_BINANCE_KEY # 密钥从环境变量读,不落明文 symbols: [BTC/USDT] trading: order_types: [market, limit] rate_limit_margin: 0.8 # 限频余量,只用八成(示意值) safety: max_daily_orders: 50 # 单日订单数上限(示意值,按策略定) kill_switch: enabled # 应急开关绑定(第 10 章) reconcile: schedule: daily # 每日对账(第 8.3 节)
从测试网切主网的门槛(全部满足才切换):
| 现象 | 常见原因 | 第一动作 |
|---|---|---|
| 测试网全过、主网拒单 | 两环境精度档位或交易规则不一致 | 重对参数级差异表,主网以官方公告为准 |
| 间歇性限频报错 | 重试逻辑叠加放大、限频余量不足 | 查重试日志的放大效应,调低 rate_limit_margin |
| key 突然失效 | 轮换到期、出口 IP 变更、权限被回收 | 按第 10 章预案先停新单,再排查 key 状态 |
| 下单成功但对不上账 | 部分成交未记账、重复成交 | 走 8.3 节二级差异流程,先停该策略新单 |
| 行情正常、下单全拒 | key 只开了读权限、账户状态异常 | 检查 key 权限勾选与账户状态页 |
排查表背后是本节的两条主线:凡涉及"单被拒",先分清是参数级差异(第一、五行,配置问题)还是账户与权限问题(五行),前者改配置,后者走权限清单复查;凡涉及"钱对不上",一律先降级运行再排查(第四行),对账纪律在第 8.3 节展开。测试网与主网行为不一致(第一行)是最消磨信心的一类问题——它的存在正是"测试网先行、清单全绿才切换"这条门槛的理由,而不是绕过它的借口。
加密所是七乘二十四小时的世界,传统券商不是。下一节看 IBKR 与 Alpaca 两条券商通道:市场时钟、T+1 结算、保证金制度三个结构性差异,会如何改写你的 scheduler 配置与风控规则。