WorkBuddy‑PythonGO Bridge
Python 接口参考
Bridge 是 WorkBuddy / MCP 与无限易 PythonGO v2 之间的本机、失败关闭型期货交易桥接器。
全部接口以 BridgeCore 的方法对外暴露,并在本地回环地址上以 JSON‑RPC 提供同一套方法名,
因此 Python 直连、MCP 工具、HTTP /rpc 三种调用方式共享同一份参数与响应结构。
两阶段提交
preview_trade 只做归一化、今昨仓拆分与硬风控;submit_trade_intent 重新计算风控并比对决策指纹后才生成可执行指令。
失败关闭
快照缺失、过期、模式不一致、心跳超时、签名无效或对账未完成时,一律拒绝而不是降级放行;熔断只能由本机 Console 解除。
结构化授权
MANUAL_LIVE 需逐笔批准或 1–60 分钟本机会话;LIMITED_AUTO 需限时、限合约、限动作、限策略版本、限额度的许可。
OBSERVE_ONLY;任何非观察模式都必须在目标无限易、PythonGO、柜台与账户组合上完成 P0 现场验收。
模式名称本身不能证明当前连接的是模拟柜台。
快速开始
下面三段代码分别对应「Python 直连」「MCP stdio」「本机 HTTP RPC」三种接入方式,三者的 method 与 params 完全一致。
1 · 安装(从源码开发)
普通用户请从 GitHub Releases 下载同版本的 ZIP 与 SHA256 文件,校验后完整解压并运行 首次安装与配置.cmd。向导会复用稳定 runtime、发现 MCP 与无限易策略目录;启动 Adapter 后即可查询,P0 只在以后启用交易时需要。
- Python ≥ 3.10(Worker 要求)
- 客户端:无限易 PythonGO v2
- Worker 仅绑定
127.0.0.1,默认OBSERVE_ONLY
2 · 三种调用方式对照
| 方式 | 入口 | 适用场景 |
|---|---|---|
| Python 直连 | BridgeCore.call(method, params) | 策略进程、回测/仿真、单元测试 |
| MCP stdio | python -m workbuddy_pythongo.mcp_server --config … | WorkBuddy / 支持 MCP 的客户端 |
| HTTP RPC | POST /rpc + Bearer token | 调试、外部脚本、本地运维看板 |
from workbuddy_pythongo.worker import build_runtime
config, database, core = build_runtime("config/bridge.json")
health = core.pythongo_health()
if not health["observation_ready"]:
raise SystemExit("bridge observation path not ready: %s" % health)
alias = core.list_account_aliases()[0]["account_alias"]
snap = core.get_account_snapshot(alias)
print(health["mode"], snap["age_seconds"])
{
"method": "get_account_snapshot",
"params": { "account_alias": "main_futures" },
"request_id": "req_7f1c9a2b"
}
TOKEN=$(cat ../data/secrets/worker.token)
curl -s http://127.0.0.1:17662/rpc \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"method":"pythongo_health","params":{}}'
--config 必须指向绝对路径):{"mcpServers":{"workbuddy-pythongo":{"command":"C:\\PATH\\TO\\python.exe","args":["-m","workbuddy_pythongo.mcp_server","--config","C:\\PATH\\TO\\config\\bridge.json"]}}}
传输与鉴权
Worker 在本机回环地址上提供单一的 POST /rpc 端点;不存在公网入口,也没有跨主机部署形态。
| 项 | 值 | 说明 |
|---|---|---|
| 基础地址 | http://127.0.0.1:17662 | 端口来自 bridge.json 的 port,默认 17662;host 必须是回环地址 |
| 唯一路径 | /rpc | 路径不等于 /rpc 时返回 404 与 {"ok": false} |
| 鉴权头 | Authorization: Bearer <worker.token> | 常量时间比较;不匹配返回 401 + UNAUTHORIZED |
| 内容类型 | application/json | 缺失或非 JSON 返回 INVALID_REQUEST |
| 请求体上限 | max_message_bytes(默认 65536) | 超出返回 INVALID_REQUEST · invalid request size |
| MCP 协议 | stdio,2025-03-26 | 服务端名 workbuddy-pythongo-bridge,能力仅 tools |
HTTP 状态码语义
| 状态码 | 含义 | 响应体 |
|---|---|---|
200 | 请求已被处理(含业务失败) | 完整信封,ok=false 时 error 非空 |
401 | token 缺失或不匹配 | {"ok":false,"error":{"code":"UNAUTHORIZED"}} |
404 | 路径不是 /rpc | {"ok": false} |
500 | Worker 未捕获异常 | INTERNAL_ERROR,需查本地日志 |
ok 与 error.code。
MCP 前端在无法连接 Worker 时会本地合成 BRIDGE_UNAVAILABLE。
调用约定与响应信封
每个方法都是「一个 method + 一个 params 对象」,参数以关键字传入;未知方法抛 METHOD_NOT_FOUND,参数类型不匹配抛 INVALID_REQUEST。
成功信封
| 字段 | 类型 | 说明 |
|---|---|---|
ok | bool | 是否成功 |
request_id | string | 回显请求 ID,未传时由 Worker 生成(req_ 前缀) |
as_of | string | ISO 8601 UTC 毫秒时间戳,服务端处理时刻 |
data | object / array | 方法返回值,失败时为 null |
warnings | array | 非阻断提示,当前版本恒为 [] |
error | object | null | 失败时为 {code, message, details} |
错误对象
| 字段 | 类型 | 说明 |
|---|---|---|
error.code | string | 机器可读错误码,见通用错误码 |
error.message | string | 人类可读说明,不含敏感信息 |
error.details | object | 结构化补充,如 {"reasons":[...]}、{"field":"…"} |
通用约定
- 时间一律 ISO 8601 UTC(毫秒),另有
age_seconds字段给出新鲜度。 - 交易所代码大写(
SHFE/DCE/CZCE/CFFEX/GFEX),合约代码原样保留。 - 金额与名义值用浮点数,手数一律正整数;避免使用
NaN/Infinity(会被拒绝)。 - 游标分页统一为
cursor/limit(list_trade_intents用after_seq),limit上限 500。 - 账户统一使用别名
account_alias;真实投资者账号不会出现在任何返回值中。
{
"ok": true,
"request_id": "req_7f1c9a2b",
"as_of": "2026-09-07T05:12:44.512Z",
"data": { "mode": "OBSERVE_ONLY", "ready": true },
"warnings": [],
"error": null
}
{
"ok": false,
"request_id": "req_7f1c9a2b",
"as_of": "2026-09-07T05:12:44.531Z",
"data": null,
"warnings": [],
"error": {
"code": "RISK_REJECTED",
"message": "current hard risk rejected the trade",
"details": { "reasons": ["QUOTE_STALE", "MAX_DAILY_ORDERS"] }
}
}
from workbuddy_pythongo.errors import BridgeError
try:
intent = core.submit_trade_intent(preview_id)
except BridgeError as exc:
print(exc.code) # RISK_REJECTED
print(exc.message) # current hard risk rejected the trade
print(exc.details) # {"reasons": ["QUOTE_STALE"]}
运行模式与门禁
四种运行模式与独立的熔断状态并存。切换模式、签名 Profile、解除熔断都只能通过本机 Console;MCP/HTTP 侧无法完成这些动作。
| 模式 | 是否可能调用报单接口 | 额外条件 |
|---|---|---|
OBSERVE_ONLY | 否(默认) | 可查询、同步、Preview 与空跑 |
SIM_SIGNAL | 会 | 仅用于已现场确认的模拟柜台;Worker 每 1 秒续约 5 秒租约 |
MANUAL_LIVE | 会 | 逐笔批准(TTL ≤ 300 秒)或 1–60 分钟本机会话 |
LIMITED_AUTO | 会 | readiness 全通过 + 存在有效结构化许可 |
旧模式名迁移映射
| 旧名称 | 迁移到 | 旧名称 | 迁移到 |
|---|---|---|---|
READ_ONLY | OBSERVE_ONLY | PAPER | SIM_SIGNAL |
DRY_RUN | OBSERVE_ONLY | LIVE_APPROVAL | MANUAL_LIVE |
HALTED | OBSERVE_ONLY | LIVE_LIMITED_AUTO | LIMITED_AUTO |
端点 Endpoints
共 31 个方法。左侧列出参数与返回字段,右侧为深色请求 / 响应卡。方法名即 BridgeCore 的方法名,
也是 MCP 工具名与 HTTP /rpc 的 method 值,三者参数完全一致。
标签语义:GET 只读 · POST 写入 / 下发指令 ·
PUT 授权(需 confirm 确认串)· DEL 撤销 / 熔断。
健康与配置
用于判断 Bridge 当前是否可以安全推进到预览与提交阶段。
pythongo_health
core.pythongo_health()返回 Worker、Adapter、队列、模式、Profile 与交易保护状态。observation_ready 单独表示查询链路可用;trade_ready 表示当前具备交易前置条件。本地交易保护开启时,查询链路仍可正常工作。
返回字段
| 字段 | 类型 | 说明 |
|---|---|---|
worker | string | Worker 自身状态,恒为 "READY" |
mode | string | 当前运行模式,见运行模式 |
halted | bool | 是否处于熔断状态 |
halt_reason | string | 熔断原因,未熔断时为空串 |
observation_ready | bool | 全部启用账户的连接、心跳、模式和保证金策略一致,可进行查询、同步和观察模式 Preview |
trade_ready | bool | 当前为非观察模式,且全部账户的 Profile、交易保护和运行门禁允许继续交易流程 |
trade_protection | object | active、kind、reason、queries_available 与 blocked_operation;kind 可为 NONE、SETUP_LOCK、ACCOUNT_CHANGE、POLICY_REVIEW 或 INCIDENT_HALT |
accounts[] | array | 每个启用账户一条,字段见下 |
unresolved_submit_unknown | int | 处于 SUBMIT_UNKNOWN 的意图数,大于 0 时应先人工核对 |
ready | bool | 全部账户就绪且未熔断 |
accounts[] 元素
| 字段 | 类型 | 说明 |
|---|---|---|
account_alias / adapter_instance | string | 账户别名与 Adapter 实例名 |
adapter_status | string | READY / OFFLINE 等心跳状态 |
heartbeat_age_seconds | number|null | 心跳年龄,超过 15 秒视为过期 |
adapter_mode / mode_match | string / bool | Adapter 侧模式及是否与 Worker 一致 |
profile_status | string | VALID / INVALID / UNKNOWN;非观察模式下必须为 VALID |
local_halt | bool | Adapter 侧本地交易锁;首次配置的 SETUP_LOCK 也会保持此值为 true,但不表示查询故障 |
connected | bool | Adapter 有未过期的 READY 心跳 |
observation_ready | bool | 该账户的查询链路、模式和保证金策略一致 |
trade_ready | bool | 该账户同时具备有效 Profile,且 Worker 与 Adapter 的交易保护均未开启 |
queue_depths | object | commands、events、dead_letter 等队列深度 |
ready | bool | 该账户是否就绪 |
health = core.pythongo_health() assert health["observation_ready"], health print(health["mode"], health["trade_protection"])
{
"worker": "READY",
"mode": "OBSERVE_ONLY",
"halted": true,
"halt_reason": "account binding changed",
"observation_ready": true,
"trade_ready": false,
"trade_protection": {
"active": true,
"kind": "ACCOUNT_CHANGE",
"reason": "account binding changed",
"queries_available": true,
"blocked_operation": "NEW_TRADES"
},
"accounts": [
{
"account_alias": "main_futures",
"adapter_instance": "pg-main",
"adapter_status": "READY",
"heartbeat_age_seconds": 2.4,
"adapter_mode": "OBSERVE_ONLY",
"mode_match": true,
"profile_status": "UNKNOWN",
"local_halt": true,
"connected": true,
"observation_ready": true,
"trade_ready": false,
"ready": false,
"queue_depths": {
"commands": 0, "command_acks": 1, "events": 0,
"control": 0, "control_acks": 0, "dead_letter": 0
}
}
],
"unresolved_submit_unknown": 0,
"ready": false
}
list_adapters
core.list_adapters()等价于 pythongo_health()["accounts"]:列出已配置的 Adapter 实例与当前健康状态(仅返回启用账户)。
返回
数组,元素结构与 pythongo_health 的 accounts[] 完全相同。
for adapter in core.list_adapters():
print(adapter["adapter_instance"], adapter["adapter_status"], adapter["ready"])
[
{
"account_alias": "main_futures",
"adapter_instance": "pg-main",
"adapter_status": "READY",
"heartbeat_age_seconds": 2.4,
"adapter_mode": "OBSERVE_ONLY",
"mode_match": true,
"profile_status": "UNKNOWN",
"local_halt": false,
"ready": true,
"queue_depths": { "commands": 0, "dead_letter": 0 }
}
]
list_account_aliases
core.list_account_aliases()列出可用的安全账户别名。永不返回真实投资者账号,仅为别名、类型与启用状态。
返回字段
| 字段 | 类型 | 说明 |
|---|---|---|
account_alias | string | 账户别名,后续所有调用的账户标识 |
account_type | string | 当前仅支持 FUTURES |
enabled | bool | 是否启用(本接口只返回启用账户) |
alias = core.list_account_aliases()[0]["account_alias"]
[
{ "account_alias": "main_futures", "account_type": "FUTURES", "enabled": true },
{ "account_alias": "sim_futures", "account_type": "FUTURES", "enabled": true }
]
get_risk_limits
core.get_risk_limits(account_alias)读取该账户的本地硬风控限额。这些限额同时用于 Preview 与 Submit 两次风控,也是 LIMITED_AUTO 许可的上界。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
返回(RiskLimits 全字段)
| 字段 | 类型 | 说明 |
|---|---|---|
max_order_volume | int | 单笔最大手数 |
max_order_notional | number | 单笔最大名义金额 |
max_position_volume_per_instrument | int | 单合约最大持仓手数 |
max_total_position_volume | int | 账户总持仓手数上限 |
max_margin_per_order | number | 单笔最大保证金占用 |
max_total_margin | number | 账户最大总保证金 |
max_risk_ratio | number | 账户风险度上限(0–100) |
max_daily_orders / max_daily_cancels | int | 每交易日委托 / 撤单次数上限 |
max_daily_loss | number | 当日最大亏损(浮亏 + 平仓盈亏) |
max_snapshot_age_seconds | int | 账户 / 持仓快照最大年龄 |
max_quote_age_seconds | int | 行情快照最大年龄 |
preview_ttl_seconds | int | Preview 有效期 |
command_ttl_seconds | int | 下发指令消息有效期 |
max_auto_authorization_minutes | int | LIMITED_AUTO 许可最长分钟数(≤720) |
max_auto_session_notional | number | 许可期内最大累计名义 |
max_auto_orders | int | 许可期内最大委托笔数 |
min_auto_order_interval_seconds | int | 两笔自动单最小间隔 |
max_auto_concurrent_orders | int | 最大并发在途单 |
max_auto_instrument_position_notional | number | 单合约最大持仓名义 |
max_auto_account_drawdown | number | 账户回撤上限 |
auto_heartbeat_max_age_seconds | int | 心跳最大年龄(默认 15) |
auto_max_queue_depth | int | 队列深度上限(默认 20) |
limits = core.get_risk_limits("main_futures")
print(limits["max_order_volume"], limits["max_daily_orders"])
{
"max_order_volume": 2,
"max_order_notional": 1000000.0,
"max_position_volume_per_instrument": 2,
"max_total_position_volume": 6,
"max_margin_per_order": 100000.0,
"max_total_margin": 400000.0,
"max_risk_ratio": 0.8,
"max_daily_orders": 20,
"max_daily_cancels": 20,
"max_daily_loss": 5000.0,
"max_snapshot_age_seconds": 15,
"max_quote_age_seconds": 10,
"preview_ttl_seconds": 60,
"command_ttl_seconds": 30,
"max_auto_authorization_minutes": 720,
"max_auto_session_notional": 1000000.0,
"max_auto_orders": 100,
"min_auto_order_interval_seconds": 1,
"max_auto_concurrent_orders": 2,
"max_auto_instrument_position_notional": 1000000.0,
"max_auto_account_drawdown": 20000.0,
"auto_heartbeat_max_age_seconds": 15,
"auto_max_queue_depth": 20
}
行情 · 账户 · 持仓
全部为只读快照读取。Bridge 不会为这些方法直接调用行情接口——先 request_sync 拉取,再读取本地一致快照。
query_instruments
core.query_instruments(filter=None, cursor=0, limit=100)列出账户白名单内的合约,以及历史上出现过行情快照的合约。结果为去重后按 (exchange, instrument_id) 排序。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
filter | string | 可选 | 大小写不敏感子串,匹配 EXCHANGE:INSTRUMENT |
cursor | int | 可选 | 起始下标,默认 0,≥ 0 |
limit | int | 可选 | 每页条数 1–500,默认 100 |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
items[] | array | {exchange, instrument_id} |
next_cursor | int|null | 下一页游标,无更多时为 null |
page = core.query_instruments(filter="au", limit=50) instruments = page["items"]
{
"items": [
{ "exchange": "SHFE", "instrument_id": "au2610" },
{ "exchange": "SHFE", "instrument_id": "au2612" }
],
"next_cursor": null
}
get_quote_snapshot
core.get_quote_snapshot(account_alias, instruments)批量读取最新一致行情快照。合约无快照时该项的 snapshot 为 null,不会抛错——需自行判断并先调用 request_sync。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
instruments[] | array | 必填 | 1–100 项,每项仅含 exchange 与 instrument_id |
返回项
| 字段 | 类型 | 说明 |
|---|---|---|
snapshot.snapshot_id | string | 快照 ID |
snapshot.captured_at / received_at | string | 采集 / 接收时间(ISO 8601 UTC) |
snapshot.age_seconds | number | 快照年龄,超过 max_quote_age_seconds 会导致风控拒绝 |
snapshot.payload | object | last_price、upper_limit_price、lower_limit_price、price_tick、volume_multiple、margin_ratio、margin_per_lot、margin_ratio_source 等 |
rows = core.get_quote_snapshot("main_futures", [
{"exchange": "SHFE", "instrument_id": "au2610"}
])
quote = rows[0]["snapshot"] # 可能为 None
if quote and quote["age_seconds"] < 10:
print(quote["payload"]["last_price"])
[
{
"exchange": "SHFE",
"instrument_id": "au2610",
"snapshot": {
"snapshot_id": "snap_9f21c4",
"captured_at": "2026-09-07T05:12:40.118Z",
"received_at": "2026-09-07T05:12:40.402Z",
"age_seconds": 3.9,
"payload": {
"last_price": 782.34,
"upper_limit_price": 860.1,
"lower_limit_price": 704.6,
"price_tick": 0.02,
"volume_multiple": 1000,
"margin_ratio": 0.12,
"margin_per_lot": 93880.0,
"margin_ratio_source": "local_reference",
"margin_ratio_source_age_hours": 6.5,
"margin_ratio_source_warning": null
}
}
}
]
get_kline_snapshot
core.get_kline_snapshot(account_alias, exchange, instrument_id, interval, count=100)读取最近一次缓存的 K 线快照,并截取最后 count 根。本方法不会直接访问行情中心,无缓存时返回 KLINE_NOT_FOUND。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
exchange / instrument_id | string | 必填 | 交易所与合约代码 |
interval | string | 必填 | 周期标识,如 1m、5m、1d(≤32 字符) |
count | int | 可选 | 1–500,默认 100 |
返回
bars 数组(已按 count 截断)、interval、age_seconds 等原始快照字段。
kline = core.get_kline_snapshot(
"main_futures", "SHFE", "au2610", "1m", count=120)
closes = [bar["close"] for bar in kline["bars"]]
{
"interval": "1m",
"age_seconds": 4.2,
"bars": [
{ "open": 781.2, "high": 782.0, "low": 781.0, "close": 781.9 },
{ "open": 781.9, "high": 782.6, "low": 781.8, "close": 782.34 }
]
}
get_account_snapshot
core.get_account_snapshot(account_alias)读取最新归一化期货账户快照(资金、保证金、风险度、盈亏)。风控使用的正是这份数据。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
snapshot_id | string | 快照 ID |
captured_at / received_at | string | 采集 / 接收时间 |
age_seconds | number | 快照年龄,超过 max_snapshot_age_seconds 触发 ACCOUNT_SNAPSHOT_STALE |
payload.trading_day | string | 交易日 YYYYMMDD,用于日计数 |
payload.dynamic_rights / balance | number | 动态权益 / 静态权益 |
payload.available | number | 可用资金,开仓保证金校验的基准 |
payload.margin / frozen_margin | number | 占用 / 冻结保证金 |
payload.risk | number | 风险度,超过 max_risk_ratio 拒绝 |
payload.close_profit / position_profit | number | 平仓盈亏 / 浮动盈亏,用于日亏校验 |
snap = core.get_account_snapshot("main_futures")
funds = snap["payload"]
print(funds["available"], funds["risk"], snap["age_seconds"])
{
"snapshot_id": "snap_31ab77",
"captured_at": "2026-09-07T05:12:38.900Z",
"received_at": "2026-09-07T05:12:39.114Z",
"age_seconds": 5.6,
"payload": {
"trading_day": "20260907",
"dynamic_rights": 982450.0,
"balance": 980000.0,
"available": 910200.0,
"margin": 72250.0,
"frozen_margin": 0.0,
"risk": 0.0735,
"close_profit": 1450.0,
"position_profit": 1000.0
}
}
get_positions
core.get_positions(account_alias, exchange=None, instrument_id=None, snapshot_kind="SIMPLE")读取一个一致的持仓快照。SIMPLE 为按合约聚合视图(风控默认使用),FULL 为含分腿明细的完整视图。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
exchange | string | 可选 | 按交易所过滤 |
instrument_id | string | 可选 | 按合约过滤 |
snapshot_kind | string | 可选 | SIMPLE(默认)或 FULL |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
snapshot_id / snapshot_kind | string | 快照标识与类型 |
captured_at / age_seconds | string / number | 采集时间与年龄 |
items[] | array | 持仓明细: exchange、instrument_id、hedgeflag、position、long{…}、short{…} |
多空两侧均含 position、frozen_closing、td_close_available、yd_close_available、td_frozen_closing、yd_frozen_closing;今昨仓拆分即依据这些字段。
pos = core.get_positions("main_futures", "SHFE", "au2610")
net = sum(item["position"] for item in pos["items"])
{
"snapshot_id": "snap_pos_5c10",
"snapshot_kind": "SIMPLE",
"captured_at": "2026-09-07T05:12:38.900Z",
"age_seconds": 5.6,
"items": [
{
"exchange": "SHFE",
"instrument_id": "au2610",
"hedgeflag": "SPECULATION",
"position": 1,
"long": {
"position": 1, "frozen_closing": 0,
"td_close_available": 1, "yd_close_available": 0,
"td_frozen_closing": 0, "yd_frozen_closing": 0
},
"short": {
"position": 0, "frozen_closing": 0,
"td_close_available": 0, "yd_close_available": 0,
"td_frozen_closing": 0, "yd_frozen_closing": 0
}
}
]
}
get_orders
core.get_orders(account_alias, status=None, trading_day=None)读取归一化后的委托记录,按 updated_at 倒序,最多 500 条。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
status | string | array | 可选 | 单个状态或 1–50 个状态组成的数组 |
trading_day | string | 可选 | YYYYMMDD |
常见状态
QUEUED、REPORTED、WORKING、PARTIALLY_FILLED、FILLED、
CANCEL_REQUESTED、CANCELLED、SEND_RETURNED、FAILED、
UNKNOWN_BROKER_STATUS、REJECTED。
其中 QUEUED、REPORTED、WORKING、PARTIALLY_FILLED、CANCEL_REQUESTED、SEND_RETURNED、UNKNOWN_BROKER_STATUS 被视为在途。
orders = core.get_orders(
"main_futures",
status=["WORKING", "PARTIALLY_FILLED"],
trading_day="20260907")
[
{
"bridge_order_id": "child_2f9a1c",
"intent_id": "intent_88ad21",
"pythongo_order_id": "PG-000123",
"exchange": "SHFE",
"instrument_id": "au2610",
"action": "OPEN_LONG",
"offset": "OPEN",
"volume": 1,
"limit_price": 782.34,
"status": "WORKING",
"trading_day": "20260907",
"updated_at": "2026-09-07T05:12:41.004Z"
}
]
get_trades
core.get_trades(account_alias, trading_day=None)读取归一化后的成交记录,按 traded_at 升序落库、返回时倒序,最多 500 条。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
trading_day | string | 可选 | YYYYMMDD |
fills = core.get_trades("main_futures", trading_day="20260907")
volume = sum(t["volume"] for t in fills)
[
{
"trade_id": "trade_4b7e02",
"intent_id": "intent_88ad21",
"child_order_id": "child_2f9a1c",
"exchange": "SHFE",
"instrument_id": "au2610",
"direction": "BUY",
"offset": "OPEN",
"volume": 1,
"price": 782.34,
"traded_at": "2026-09-07T05:12:43.771Z",
"trading_day": "20260907"
}
]
get_pending_signals
core.get_pending_signals(filters=None, cursor=0, limit=100)读取已落库的确定性信号(含 TTL 与冷却期保护)。v1 的 filters 未定义任何字段,必须省略或传空对象。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
filters | object | 可选 | v1 必须为 {} 或省略 |
cursor | int | 可选 | 上一页最后一条的 seq |
limit | int | 可选 | 1–500,默认 100 |
返回项
seq 为游标值;其余为信号负载:signal_id、source_type、account_alias、exchange、instrument_id、signal_type、rule_set_id、rule_version、created_at、expires_at。
page = core.get_pending_signals(limit=20)
for item in page["items"]:
print(item["seq"], item["signal_id"], item["signal_type"])
{
"items": [
{
"seq": 41,
"signal_id": "sig_9c1f2e77a0b34d15",
"source_type": "DETERMINISTIC_RULE",
"account_alias": "main_futures",
"exchange": "SHFE",
"instrument_id": "au2610",
"signal_type": "CROSS_UP",
"rule_set_id": "ma-cross-v1",
"rule_version": "1.0.2",
"created_at": "2026-09-07T05:10:02.118Z",
"expires_at": "2026-09-07T05:15:02.118Z"
}
],
"next_cursor": null
}
意图 · 审计 · 授权状态
交易意图(trade intent)是提交后的唯一事实来源:一个意图包含若干子单(child orders)与关联成交。
get_trade_intent
core.get_trade_intent(intent_id)读取单个意图、异步提交状态、其下全部子单以及关联成交。状态处于 SUBMIT_UNKNOWN 时应人工核对柜台后再决定下一步。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
intent_id | string | 必填 | 意图 ID(intent_ 前缀) |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
async_status | object | accepted、state、queue_delivered、native_send_returned、broker_acknowledged、terminal、poll_method、poll_after_ms |
intent | object | 意图行:seq、status、action、exchange、instrument_id、requested_volume、execution_mode、source_signal_id 等 |
request | object | 落库时的完整负载,含原始 request 与当时 preview 快照 |
children[] | array | 子单:child_no、client_order_key、memo_token、action、offset、volume、status |
trades[] | array | 与该意图关联的成交 |
意图状态
PERSISTED → QUEUED → ACTIVE → FILLED;终态还包括 OBSERVED、CANCELLED、PARTIALLY_FILLED_CANCELLED、FAILED 和 SUBMIT_UNKNOWN。QUEUED 只代表 Bridge 已可靠投递,不代表柜台接单。
detail = core.get_trade_intent("intent_88ad21")
print(detail["intent"]["status"])
for child in detail["children"]:
print(child["child_no"], child["status"], child["volume"])
{
"async_status": {
"accepted": true,
"state": "ACTIVE",
"queue_delivered": true,
"native_send_returned": true,
"broker_acknowledged": true,
"terminal": false,
"poll_method": "get_trade_intent",
"poll_after_ms": 150
},
"intent": {
"intent_id": "intent_88ad21",
"preview_id": "preview_1c77de",
"account_alias": "main_futures",
"status": "WORKING",
"action": "OPEN_LONG",
"exchange": "SHFE",
"instrument_id": "au2610",
"requested_volume": 1,
"execution_mode": "SIM_SIGNAL",
"source_signal_id": "sig-20260907-0001",
"seq": 128,
"created_at": "2026-09-07T05:12:44.512Z",
"updated_at": "2026-09-07T05:12:45.010Z"
},
"request": {
"intent_id": "intent_88ad21",
"preview_id": "preview_1c77de",
"request": { "account_alias": "main_futures" },
"preview": { "risk": { "allowed": true, "reasons": [] } }
},
"children": [
{
"child_order_id": "child_2f9a1c",
"child_no": 1,
"client_order_key": "wb_8Vn2Qx7bTk1Lm0Za",
"memo_token": "WB3F9A2C7701",
"action": "OPEN_LONG",
"offset": "OPEN",
"volume": 1,
"limit_price": 782.34,
"status": "WORKING"
}
],
"trades": []
}
list_trade_intents
core.list_trade_intents(status=None, after_seq=0, limit=100)按稳定序号 seq 升序列出意图,适合做增量拉取:用返回值的 next_seq 作为下一次 after_seq。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
status | string | array | 可选 | 状态过滤,1–50 个 |
after_seq | int | 可选 | 仅返回 seq > after_seq 的意图 |
limit | int | 可选 | 1–500,默认 100 |
page = core.list_trade_intents(status="WORKING", after_seq=120, limit=50) cursor = page["next_seq"]
{
"items": [
{
"intent_id": "intent_88ad21",
"seq": 128,
"status": "WORKING",
"action": "OPEN_LONG",
"exchange": "SHFE",
"instrument_id": "au2610",
"execution_mode": "SIM_SIGNAL",
"updated_at": "2026-09-07T05:12:45.010Z"
}
],
"next_seq": null
}
get_reconciliation_status
core.get_reconciliation_status(account_alias)读取对账状态。required=true 时所有新开仓都会被拒绝(RECONCILIATION_REQUIRED),需先 request_reconciliation 并等待事实刷新。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
required | bool | 是否需要重新对账 |
latest_run | object | null | 最近一次对账运行:run_id、status、started_at、completed_at、result_json |
recon = core.get_reconciliation_status("main_futures")
if recon["required"]:
core.request_reconciliation("main_futures", "manual check")
{
"required": false,
"latest_run": {
"run_id": "recon_5ad1c9",
"account_alias": "main_futures",
"status": "SUCCESS",
"started_at": "2026-09-07T01:30:00.000Z",
"completed_at": "2026-09-07T01:30:02.511Z",
"result_json": "{\"account_alias\":\"main_futures\"}"
}
}
get_audit_events
core.get_audit_events(correlation_id=None, cursor=0, limit=100)读取本地审计事件流(授权、提交、撤单、熔断等)。correlation_id 在已读取页内做子串匹配过滤。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
correlation_id | string | 可选 | 在 details_json 中做子串匹配 |
cursor | int | 可选 | 上一页最后一条 seq |
limit | int | 可选 | 1–500,默认 100 |
返回项
seq、occurred_at、actor(mcp / worker)、action、account_alias、object_id、details_json(JSON 字符串)。
events = core.get_audit_events(limit=50)
for e in events["items"]:
print(e["seq"], e["action"], e["actor"])
{
"items": [
{
"seq": 512,
"occurred_at": "2026-09-07T05:12:44.600Z",
"actor": "mcp",
"action": "SUBMIT_TRADE_INTENT",
"account_alias": "main_futures",
"object_id": "intent_88ad21",
"details_json": "{\"preview_id\":\"preview_1c77de\",\"children\":1,\"mode\":\"SIM_SIGNAL\"}"
}
],
"next_cursor": null
}
get_manual_authorization_status
core.get_manual_authorization_status(account_alias)读取 MANUAL_LIVE 的定时会话与一次性批准状态。会话与批准在 Worker 重启后全部失效,需要重新授权。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
mode / halted | string / bool | 当前模式与熔断状态 |
timed_session | object | null | 生效中的会话:session_id、expires_at、unlimited_order_count |
session_remaining_seconds | int | 会话剩余秒数 |
live_until / live_active | string / bool | LIVE 窗口截止时间与是否生效 |
unused_one_time_approvals | int | 未使用且未过期的一次性批准数 |
authorized | bool | 综合判断是否已具备人工 LIVE 授权 |
st = core.get_manual_authorization_status("main_futures")
print(st["live_active"], st["session_remaining_seconds"], st["authorized"])
{
"account_alias": "main_futures",
"mode": "MANUAL_LIVE",
"halted": false,
"timed_session": {
"session_id": "manual_session_41ab",
"account_alias": "main_futures",
"created_at": "2026-09-07T05:00:00.000Z",
"expires_at": "2026-09-07T05:30:00.000Z",
"reason": "现场人工值守",
"actor": "mcp",
"unlimited_order_count": true
},
"session_remaining_seconds": 1035,
"live_until": "2026-09-07T05:30:00.000Z",
"live_active": true,
"unused_one_time_approvals": 0,
"authorized": true
}
get_limited_auto_status
core.get_limited_auto_status(account_alias)读取最新许可、策略、用量预算、暂停状态与健康原因。未签发过许可时返回 configured=false 与 status="NONE"。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
configured / active | bool | 是否签发过许可 / 许可当前是否生效 |
status | string | NONE / ACTIVE / PAUSED / REVOKED / EXPIRED / INVALID |
permit_id / policy_hash / generation | string / string / int | 许可标识、策略哈希与世代号(撤销或恢复都会轮换) |
starts_at / expires_at / remaining_seconds | string / string / int | 许可有效期 |
policy | object | 完整策略:允许合约、动作、交易时段、各项额度 |
usage | object | 已用笔数与累计名义 |
remaining_orders / remaining_notional | int / number | 剩余预算 |
health_reasons | array | 非空的健康原因,如 AUTO_ADAPTER_NOT_READY |
st = core.get_limited_auto_status("main_futures")
if not st["active"]:
print(st["status"], st["health_reasons"])
{
"configured": true,
"active": true,
"status": "ACTIVE",
"permit_id": "auto_permit_7c01",
"policy_hash": "e91f77c2a1b04d5e",
"generation": 3,
"starts_at": "2026-09-07T05:00:00.000Z",
"expires_at": "2026-09-07T07:00:00.000Z",
"remaining_seconds": 6435,
"pause_reason": null,
"revoked_reason": null,
"policy": {
"policy_version": 1,
"timezone": "Asia/Shanghai",
"allowed_instruments": ["SHFE:au2610"],
"allowed_actions": ["OPEN_LONG", "CLOSE_TODAY_LONG"],
"trading_windows": [{ "start": "09:00", "end": "14:55" }],
"max_orders": 10,
"max_order_volume": 1,
"max_session_notional": 800000.0,
"max_concurrent_orders": 1,
"min_order_interval_seconds": 30
},
"usage": { "order_count": 2, "notional": 156468.0 },
"remaining_orders": 8,
"remaining_notional": 643532.0,
"health_reasons": []
}
同步与预览
提交前必须先同步快照、再生成预览。预览本身不产生任何可执行指令。
request_sync
core.request_sync(account_alias, scopes, instruments=None, kline=None, purpose="GENERAL")向 Adapter 下发一次快照刷新请求,写入签名文件队列。该方法永不创建交易意图;返回值只代表指令已投递,不代表快照已更新——需轮询读取接口确认。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
scopes[] | array | 必填 | ACCOUNT、POSITION、ORDER、TRADE、QUOTE、KLINE 的非空唯一子集 |
instruments[] | array | 可选 | 最多 100 项;QUOTE / KLINE 场景必填 |
kline | object | 可选 | {interval, count},count 1–500;KLINE 场景必填 interval |
purpose | string | 可选 | GENERAL(默认)或 TRADE;交易热路径禁止包含 KLINE |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
message_id | string | 队列消息 ID,可用于追踪 |
status | string | DELIVERED 表示已落队列 |
command_type | string | 固定为 REQUEST_SYNC |
core.request_sync(
"main_futures",
purpose="TRADE",
scopes=["ACCOUNT", "POSITION", "QUOTE"],
instruments=[{"exchange": "SHFE", "instrument_id": "au2610"}])
{
"message_id": "msg_5f21c8aa",
"status": "DELIVERED",
"command_type": "REQUEST_SYNC",
"purpose": "TRADE"
}
preview_trade
core.preview_trade(trade_request)
归一化交易请求、按今昨仓策略拆分子单、执行全部本地硬风控,并落库一份带有效期的预览。
不会生成任何可执行指令。返回的 decision_fingerprint 会在提交时重新计算并比对,快照变化即失效。
trade_request 结构
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
instrument | object | 必填 | 仅含 exchange、instrument_id |
action | string | 必填 | OPEN_LONG、OPEN_SHORT、CLOSE_LONG、CLOSE_SHORT、CLOSE_TODAY_LONG、CLOSE_TODAY_SHORT、CLOSE_YESTERDAY_LONG、CLOSE_YESTERDAY_SHORT |
sizing | object | 必填 | {type:"FIXED_VOLUME", value:<正整数>} |
price_policy | object | 必填 | {type:"FIXED_LIMIT", limit_price:>0, max_deviation_pct:0–1},max_deviation_pct 默认 0.02 |
close_policy | string | 可选 | TODAY_FIRST / YESTERDAY_FIRST / EXPLICIT_ONLY,缺省用账户配置 |
hedge_flag | string | 必填 | v1 仅支持 SPECULATION |
execution_mode | string | 必填 | 必须与 Worker 当前模式一致,否则 MODE_MISMATCH |
source | object | 必填 | {type, signal_id, rule_set_id?, rule_version?},signal_id 用于幂等 |
返回关键字段
| 字段 | 类型 | 说明 |
|---|---|---|
preview_id / risk_decision_id | string | 预览与风控决策 ID |
created_at / expires_at | string | 预览有效期 = preview_ttl_seconds |
children[] | array | 拆分后的子单:action、direction、offset、volume |
resolved_limit_price / notional / margin_estimate | number | 最终价格、名义金额与保证金估算 |
risk | object | {allowed, reasons[]},reasons 见风控原因 |
decision_material / decision_fingerprint | object / string | 决策材料与其哈希,提交时比对 |
preview = core.preview_trade({
"account_alias": "main_futures",
"instrument": {"exchange": "SHFE", "instrument_id": "au2610"},
"action": "OPEN_LONG",
"sizing": {"type": "FIXED_VOLUME", "value": 1},
"price_policy": {
"type": "FIXED_LIMIT",
"limit_price": 782.34,
"max_deviation_pct": 0.02},
"close_policy": "TODAY_FIRST",
"hedge_flag": "SPECULATION",
"execution_mode": "OBSERVE_ONLY",
"source": {"type": "MANUAL_TEST", "signal_id": "sig-20260907-0001"}})
assert preview["risk"]["allowed"], preview["risk"]["reasons"]
{
"account_alias": "main_futures",
"instrument": { "exchange": "SHFE", "instrument_id": "au2610" },
"action": "OPEN_LONG",
"execution_mode": "OBSERVE_ONLY",
"requested_volume": 1,
"resolved_limit_price": 782.34,
"close_policy": "TODAY_FIRST",
"children": [
{ "action": "OPEN_LONG", "direction": "BUY", "offset": "OPEN", "volume": 1 }
],
"notional": 782340.0,
"margin_estimate": 93880.0,
"risk": { "allowed": true, "reasons": [] },
"decision_material": {
"available": 910200.0,
"margin": 72250.0,
"risk": 0.0735,
"pnl": 2450.0,
"quote_guard": {
"price_tick": 0.02,
"volume_multiple": 1000,
"tick_aligned": true,
"within_daily_limit": true,
"within_max_deviation": true
},
"daily_counts": { "orders": 0, "cancels": 0, "total_position_volume": 0 }
},
"decision_fingerprint": "b7c1d9e4f2a8",
"preview_id": "preview_1c77de",
"risk_decision_id": "risk_3ad0f1",
"created_at": "2026-09-07T05:12:44.512Z",
"expires_at": "2026-09-07T05:13:44.512Z",
"request_hash": "9de1a7c02b55"
}
执行与撤单
提交阶段会重新执行完整硬风控、比对决策指纹并校验授权,任一环节不通过即拒绝。
submit_trade_intent
core.submit_trade_intent(preview_id, approval_context=None)
消费一份未过期的预览:重算风控 → 校验授权 → 生成意图与子单 → 写入签名队列。
命令可靠落库并进入队列后立即返回异步状态,不等待 PythonGO 报单返回、柜台确认或成交。
MANUAL_LIVE 模式下若无生效会话,需在 approval_context.local_approval_id 传入一次性批准 ID。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
preview_id | string | 必填 | 预览 ID |
approval_context | object | 可选 | {local_approval_id},MANUAL_LIVE 逐笔批准时必填 |
返回
与 get_trade_intent 结构一致:{async_status, intent, request, children[], trades[]}。未终态时按 async_status.poll_after_ms 再查询。
提交时序
- 预检:预览存在、未过期、未被消费;
LIMITED_AUTO预检失败会暂停许可。 - 事务内:比对
decision_fingerprint→ 复核风控 → 校验授权 → 落库意图与子单。 - 子单按顺序下发:第 1 条可靠发布后变为
QUEUED,后续为BLOCKED_SEQUENCE,前一条终结后才放行。 - 结果未知(
PRE_SUBMIT、SUBMIT_CALLED、SUBMIT_UNKNOWN)不会自动重发。
detail = core.submit_trade_intent(preview["preview_id"]) print(detail["intent"]["intent_id"], detail["intent"]["status"])
approval = core.authorize_manual_trade(
preview_id=preview["preview_id"],
reason="现场确认后单笔放行",
confirm="AUTHORIZE-MANUAL-TRADE",
live_minutes=5)
detail = core.submit_trade_intent(
preview["preview_id"],
{"local_approval_id": approval["approval_context"]["local_approval_id"]})
{
"async_status": {
"accepted": true,
"state": "QUEUED",
"queue_delivered": true,
"native_send_returned": false,
"broker_acknowledged": false,
"terminal": false,
"poll_method": "get_trade_intent",
"poll_after_ms": 150
},
"intent": {
"intent_id": "intent_88ad21",
"preview_id": "preview_1c77de",
"status": "QUEUED",
"action": "OPEN_LONG",
"requested_volume": 1,
"execution_mode": "SIM_SIGNAL"
},
"children": [
{
"child_order_id": "child_2f9a1c",
"child_no": 1,
"status": "QUEUED",
"volume": 1,
"limit_price": 782.34,
"memo_token": "WB3F9A2C7701"
}
],
"trades": []
}
cancel_order
core.cancel_order(account_alias, bridge_order_id, reason)请求撤销本桥接器拥有的单个在途委托。重复调用返回上一次的指令并带 duplicate=true,不会产生第二条撤单。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
bridge_order_id | string | 必填 | 子单 ID(child_ 前缀),非柜台委托号 |
reason | string | 必填 | 1–200 字符,写入审计 |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
message_id | string | 撤单指令消息 ID |
status | string | 指令投递状态 |
duplicate | bool | 仅重复调用时出现,表示复用了已有指令 |
res = core.cancel_order(
"main_futures", "child_2f9a1c", "价格偏离,撤单重报")
print(res["status"], res.get("duplicate", False))
{
"message_id": "msg_77ac31",
"status": "DELIVERED",
"command_type": "CANCEL_ORDER"
}
授权 · 熔断 · 恢复
所有 PUT 类方法都要求传入精确的 confirm 确认串,缺失或不匹配一律返回 LOCAL_CONFIRMATION_REQUIRED。
authorize_manual_trade
core.authorize_manual_trade(preview_id, reason, confirm, live_minutes=10, approval_ttl_seconds=30)为一份未过期的 MANUAL_LIVE 预览签发一次性批准。调用前必须已取得用户明确确认,并已复核预览的模式、合约、方向与手数。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
preview_id | string | 必填 | 预览 ID |
reason | string | 必填 | 1–200 字符,写入审计 |
confirm | string | 必填 | 必须等于 AUTHORIZE-MANUAL-TRADE |
live_minutes | int | 可选 | 1–60,默认 10;延长本机 LIVE 窗口 |
approval_ttl_seconds | int | 可选 | 1–300,默认 30;不超过预览剩余有效期 |
返回
preview_id、approval_context.local_approval_id(提交时回填)、live_until、approval_expires_at。
approval = core.authorize_manual_trade(
preview_id=preview["preview_id"],
reason="已与用户逐字段确认",
confirm="AUTHORIZE-MANUAL-TRADE",
live_minutes=5,
approval_ttl_seconds=30)
approval_id = approval["approval_context"]["local_approval_id"]
{
"preview_id": "preview_1c77de",
"approval_context": { "local_approval_id": "approval_2b91ff" },
"live_until": "2026-09-07T05:17:44.512Z",
"approval_expires_at": "2026-09-07T05:13:14.512Z"
}
authorize_manual_session
core.authorize_manual_session(account_alias, minutes, reason, confirm)在 1–60 分钟窗口内放开无限笔数的人工 LIVE 交易。每一笔仍然需要重新同步、重新预览并通过全部风控——会话只替代逐笔批准,不放宽任何限额。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
minutes | int | 必填 | 1–60 |
reason | string | 必填 | 1–200 字符 |
confirm | string | 必填 | 必须等于 AUTHORIZE-TIMED-MANUAL-TRADING |
session = core.authorize_manual_session(
account_alias="main_futures",
minutes=30,
reason="人工值守窗口",
confirm="AUTHORIZE-TIMED-MANUAL-TRADING")
{
"session_id": "manual_session_41ab",
"account_alias": "main_futures",
"created_at": "2026-09-07T05:00:00.000Z",
"expires_at": "2026-09-07T05:30:00.000Z",
"reason": "人工值守窗口",
"actor": "mcp",
"unlimited_order_count": true
}
revoke_manual_session
core.revoke_manual_session(account_alias, reason, confirm)立即撤销定时会话,并让该账户所有未使用的一次性批准立即过期,随后重写本机授权文件为空权限。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
reason | string | 必填 | 1–200 字符 |
confirm | string | 必填 | 必须等于 REVOKE-TIMED-MANUAL-TRADING |
core.revoke_manual_session(
account_alias="main_futures",
reason="值守结束",
confirm="REVOKE-TIMED-MANUAL-TRADING")
{ "account_alias": "main_futures", "revoked": true }
check_limited_auto_readiness
core.check_limited_auto_readiness(account_alias)执行失败关闭的 readiness 检查并持久化结果(同时写入一条对账运行记录)。不会签发任何许可;若检查出严重原因,会把当前许可置为暂停。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
account_alias | string | 账户别名 |
ready | bool | reasons 为空时为 true |
reasons[] | array | 如 AUTO_ADAPTER_NOT_READY、AUTO_QUEUE_BACKLOG、AUTO_RECONCILIATION_REQUIRED |
scan_error_type | string | null | 事件扫描异常类型 |
reconciliation_run_id | string | 本次检查对应的对账运行 ID |
ready = core.check_limited_auto_readiness("main_futures")
if not ready["ready"]:
raise SystemExit(ready["reasons"])
{
"account_alias": "main_futures",
"ready": false,
"reasons": ["AUTO_ADAPTER_NOT_READY"],
"scan_error_type": null,
"reconciliation_run_id": "recon_9ac2f0"
}
authorize_limited_auto
core.authorize_limited_auto(account_alias, instruments, actions, …)
签发一份有界、与策略版本绑定的 LIMITED_AUTO 许可。许可包含允许合约、允许动作、交易时段、
单笔/会话额度、并发与最小间隔等完整策略,并计算 policy_hash。
本方法不会改变运行模式,也不会解除熔断。签发时旧许可会被置为 REVOKED。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
instruments[] | array | 必填 | 1–100 项且唯一,必须落在账户白名单内 |
actions[] | array | 必填 | 1–8 项且唯一,取值为 8 个期货动作 |
source_type / rule_set_id / rule_version | string | 必填 | 策略来源与版本,≤100 字符;连续失败后需新版本重新授权 |
max_order_notional | number | 必填 | > 0,且不超过账户硬限额 |
max_order_volume | int | 必填 | ≥ 1 |
max_session_notional | number | 必填 | > 0,须落在配置的自动限额区间内 |
max_orders | int | 必填 | 许可期内最大委托笔数 |
max_concurrent_orders | int | 必填 | 不超过配置硬上限 |
max_instrument_position_notional | number | 必填 | 单合约持仓名义上限 |
max_account_drawdown | number | 必填 | 账户回撤上限 |
trading_windows[] | array | 必填 | 1–8 个 {start:"HH:MM", end:"HH:MM"},不得覆盖整天 |
reason | string | 必填 | 1–500 字符 |
confirm | string | 必填 | 必须等于 AUTHORIZE-LIMITED-AUTO-P1 |
minutes | int | 可选 | 1–720,受 max_auto_authorization_minutes 约束 |
min_order_interval_seconds | int | 可选 | ≥ 配置的最小间隔 |
max_consecutive_failures | int | 可选 | 1–100,超过后需重新签发新版本许可 |
返回
完整的 limited-auto 状态对象(含 policy 与 usage)。
core.authorize_limited_auto(
account_alias="main_futures",
instruments=[{"exchange": "SHFE", "instrument_id": "au2610"}],
actions=["OPEN_LONG", "CLOSE_TODAY_LONG"],
source_type="DETERMINISTIC_RULE",
rule_set_id="ma-cross-v1",
rule_version="1.0.2",
max_order_notional=800000.0,
max_order_volume=1,
max_session_notional=800000.0,
max_orders=10,
max_concurrent_orders=1,
max_instrument_position_notional=800000.0,
max_account_drawdown=5000.0,
minutes=120,
min_order_interval_seconds=30,
trading_windows=[{"start": "09:00", "end": "14:55"}],
reason="已通过 P0 与 readiness",
confirm="AUTHORIZE-LIMITED-AUTO-P1")
{
"configured": true,
"active": true,
"status": "ACTIVE",
"permit_id": "auto_permit_7c01",
"policy_hash": "e91f77c2a1b04d5e",
"generation": 3,
"expires_at": "2026-09-07T07:00:00.000Z",
"policy": {
"policy_version": 1,
"timezone": "Asia/Shanghai",
"baseline_equity": 982450.0,
"allowed_instruments": ["SHFE:au2610"],
"allowed_actions": ["CLOSE_TODAY_LONG", "OPEN_LONG"],
"trading_windows": [{ "start": "09:00", "end": "14:55" }],
"max_orders": 10,
"max_consecutive_failures": 3
},
"usage": { "order_count": 0, "notional": 0.0 },
"remaining_orders": 10,
"remaining_notional": 800000.0,
"health_reasons": []
}
resume_limited_auto
core.resume_limited_auto(account_alias, reason, confirm)在 readiness 恢复后恢复一份处于 PAUSED 且未过期的许可,并轮换 generation。已撤销、已过期或连续失败超限的许可不会被恢复。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
reason | string | 必填 | 1–500 字符 |
confirm | string | 必填 | 必须等于 RESUME-LIMITED-AUTO-P1 |
core.resume_limited_auto(
account_alias="main_futures",
reason="心跳恢复,readiness 已通过",
confirm="RESUME-LIMITED-AUTO-P1")
{
"configured": true,
"active": true,
"status": "ACTIVE",
"permit_id": "auto_permit_7c01",
"generation": 4,
"health_reasons": []
}
revoke_limited_auto
core.revoke_limited_auto(account_alias, reason, confirm)立即撤销当前许可并轮换 generation,同时重写本机授权文件。撤销后必须重新签发才能继续自动交易。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
reason | string | 必填 | 1–500 字符 |
confirm | string | 必填 | 必须等于 REVOKE-LIMITED-AUTO-P1 |
core.revoke_limited_auto(
account_alias="main_futures",
reason="行情异常,停止自动交易",
confirm="REVOKE-LIMITED-AUTO-P1")
{
"configured": true,
"active": false,
"status": "REVOKED",
"permit_id": "auto_permit_7c01",
"generation": 5,
"revoked_reason": "行情异常,停止自动交易"
}
halt_trading
core.halt_trading(reason)
全局熔断,失败关闭。立即清空定时会话与未使用批准、撤销全部 LIMITED_AUTO 许可,并向每个启用账户写入本地熔断文件。
只能由本机 Console 解除,解除后强制回到 OBSERVE_ONLY。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
reason | string | 必填 | 1–500 字符,写入审计与熔断文件 |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
halted | bool | 恒为 true |
reason | string | 熔断原因 |
adapter_file_failures[] | array | 本地熔断文件写入失败的账户,非空时必须人工介入 |
res = core.halt_trading("行情源异常,人工熔断")
assert not res["adapter_file_failures"], res
{
"halted": true,
"reason": "行情源异常,人工熔断",
"adapter_file_failures": []
}
request_reconciliation
core.request_reconciliation(account_alias, reason)把账户标记为「需要对账」,并立刻请求账户、持仓、委托、成交四类事实刷新。对账完成前,所有新开仓都会被拒绝。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
account_alias | string | 必填 | 账户别名 |
reason | string | 必填 | 非空,写入对账记录 |
返回
| 字段 | 类型 | 说明 |
|---|---|---|
run_id | string | 对账运行 ID |
status | string | REQUESTED |
sync | object | 同步指令投递结果(message_id / status) |
res = core.request_reconciliation("main_futures", "疑似漏单,人工发起对账")
print(res["run_id"], res["sync"]["status"])
{
"run_id": "recon_5ad1c9",
"status": "REQUESTED",
"sync": {
"message_id": "msg_b1e774",
"status": "DELIVERED",
"command_type": "REQUEST_SYNC"
}
}
通用错误码
所有业务失败都通过响应体的 error 对象表达:code 为机器可读码、message 为人类可读说明、
details 携带结构化补充(如 reasons 数组)。Python 直连时它们会作为 BridgeError 抛出。
错误响应结构
{
"ok": false,
"request_id": "req_7f1c9a2b",
"as_of": "2026-09-07T05:12:44.531Z",
"data": null,
"warnings": [],
"error": {
"code": "PREVIEW_EXPIRED",
"message": "preview has expired",
"details": {}
}
}
from workbuddy_pythongo.errors import BridgeError
try:
core.submit_trade_intent(preview_id)
except BridgeError as exc:
if exc.code in ("PREVIEW_EXPIRED", "SNAPSHOT_CHANGED"):
preview = core.preview_trade(trade_request) # 重新预览
elif exc.code == "TRADING_HALTED":
raise SystemExit("已熔断,需本机 Console 解除")
else:
raise
ValidationError 是 BridgeError 的子类,code 恒为 INVALID_REQUEST,代表参数校验失败。错误码总表
| error.code | 触发场景与处理建议 |
|---|---|
| 传输与通用 | |
UNAUTHORIZED | Bearer token 缺失或不匹配(HTTP 401)。检查 worker.token 是否与 Worker 同版本生成 |
BRIDGE_UNAVAILABLE | MCP 前端无法连接本机 Worker。确认 Worker 进程在运行、端口未被占用 |
INTERNAL_ERROR | Worker 未捕获异常(HTTP 500)。查本地日志,保留 request_id |
INVALID_REQUEST | 参数类型、范围、字段集或信封非法。按 message 修正后重试 |
METHOD_NOT_FOUND | 方法名不存在。核对方法名拼写与版本 |
CONFIG_ERROR / CONFIG_REQUIRED | bridge.json 缺失、字段未知、取值越界或缺少 --config。修配置后重启 Worker |
| 账户与 Profile | |
ACCOUNT_NOT_FOUND | 别名不存在或账户未启用。用 list_account_aliases 核对 |
PROFILE_INVALID | 签名 Profile 缺失、占位未替换、构建绑定过期或与 Adapter 不匹配。需本机 Console 重新签名 |
| 快照与新鲜度 | |
ACCOUNT_SNAPSHOT_MISSING / ACCOUNT_SNAPSHOT_STALE / ACCOUNT_SNAPSHOT_INCOMPLETE | 账户快照缺失 / 超过 max_snapshot_age_seconds / P0 字段不全。先 request_sync 拉 ACCOUNT |
POSITION_SNAPSHOT_MISSING / POSITION_SNAPSHOT_STALE | 持仓快照缺失或过期。同步 POSITION 后再预览 |
QUOTE_STALE / QUOTE_INCOMPLETE | 行情过期或字段不全(P0 场景)。同步 QUOTE |
KLINE_NOT_FOUND | 无 K 线缓存。先以 KLINE scope 同步 |
ADAPTER_NOT_READY | Adapter 心跳非 READY 或不新鲜。检查无限易 / PythonGO 是否已启动并登录 |
| 交易与风控 | |
RISK_REJECTED | 硬风控拒绝。details.reasons 给出全部原因,见下方对照表 |
SNAPSHOT_CHANGED | 提交时决策指纹已变(快照被刷新)。必须重新 preview_trade |
INSTRUMENT_NOT_ALLOWED | 合约不在账户白名单内,或许可合约越界 |
POSITION_INSUFFICIENT | 平仓量超过今仓 / 昨仓可用量 |
EXPLICIT_OFFSET_REQUIRED | 账户 close_policy=EXPLICIT_ONLY,禁止笼统平仓 |
PREVIEW_NOT_FOUND / PREVIEW_EXPIRED / PREVIEW_ALREADY_CONSUMED | 预览不存在、已过期(preview_ttl_seconds)或已被消费。重新预览 |
ORDER_NOT_FOUND / ORDER_ALREADY_TERMINAL / ORDER_NOT_ACKNOWLEDGED | 子单不存在、已终结、或柜台委托号尚未回报(无法撤单) |
INTENT_NOT_FOUND | 意图 ID 不存在 |
| 授权 | |
LOCAL_CONFIRMATION_REQUIRED | confirm 未传或与要求字符串不完全一致 |
MANUAL_AUTHORIZATION_REQUIRED | 缺少一次性批准,或批准已过期 / 已使用 / 绑定了其它预览 |
LIVE_NOT_ENABLED | Worker 或预览不在 MANUAL_LIVE、已熔断、或 LIVE 窗口未生效 |
MODE_MISMATCH | 请求的 execution_mode 与 Worker 当前模式不一致 |
AUTO_PERMIT_REQUIRED | LIMITED_AUTO 下没有生效许可 |
AUTO_POLICY_REJECTED | 许可策略拒绝该笔(合约、动作、时段、额度、间隔、并发等) |
AUTO_NOT_READY | readiness 检查未通过。details.reasons 给出原因 |
AUTO_PERMIT_NOT_FOUND / AUTO_PERMIT_EXPIRED | 没有处于 PAUSED 的许可,或该许可已过期 |
AUTO_ACCOUNT_DRAWDOWN_EXCEEDED / AUTO_ACCOUNT_EQUITY_UNAVAILABLE | 账户回撤超限,或取不到正的 dynamic_rights/balance |
AUTO_STRATEGY_REAUTHORIZATION_REQUIRED | 连续失败达到上限,必须换 rule_version 重新签发许可 |
| 熔断与对账 | |
TRADING_HALTED | 已熔断。禁止重试任何交易动作,需本机 Console 解除并回到 OBSERVE_ONLY |
| 消息、队列与签名 | |
MESSAGE_SCHEMA_INVALID | 信封字段集、协议版本或消息类型非法 |
MESSAGE_EXPIRED / CLOCK_SKEW | 消息超过 TTL,或 issued_at 在未来(默认容忍 5 秒时钟偏移) |
MESSAGE_TOO_LARGE | 消息或文件超过 max_message_bytes |
SIGNATURE_INVALID | 签名不匹配或 key_id 未知。检查密钥文件是否被替换 |
ACCOUNT_BINDING_MISMATCH | 事件落到了错误的账户分区。属严重异常,应对账后人工处理 |
| P0 现场验收(Console) | |
P0_GATE_FAILED | P0 探针要求 OBSERVE_ONLY 且本地熔断生效 |
P0_RISK_REJECTED / P0_POSITION_GATE | P0 腿超出隔离限额,或持仓前置条件不满足 |
P0_PRICE_INVALID / P0_PRICE_NOT_PASSIVE | 价格未对齐最小变动价位,或限价不够被动 |
P0_VALIDATION_REJECTED | 不支持的 P0 动作,或校验腿绑定关系不正确 |
| 保证金参考数据 | |
MARGIN_POLICY_MIGRATION_REQUIRED | 旧配置或策略代次/哈希不一致;日常刷新不会修改配置或 Profile,须由本机显式运行 migrate-margin-policy |
MARGIN_REFERENCE_CONFIG_ERROR | Adapter 配置不可读,或没有启用账户的保证金文件路径 |
MARGIN_REFERENCE_INVALID / MARGIN_REFERENCE_READ_FAILED | 本地保证金 CSV 不是有效 UTF-8、没有唯一合约记录,或读取失败。此时不会回退到宽松保证金 |
风控原因对照(details.reasons)
硬风控拒绝时,error.details.reasons 会给出全部原因。以下是 preview_trade 与 submit_trade_intent 可能产生的原因。
| reason | 含义 | reason | 含义 |
|---|---|---|---|
INSTRUMENT_NOT_ALLOWED | 合约不在白名单 | MAX_ORDER_NOTIONAL | 超过单笔名义上限 |
ACCOUNT_SNAPSHOT_MISSING | 无账户快照 | MAX_MARGIN_PER_ORDER | 超过单笔保证金上限 |
ACCOUNT_SNAPSHOT_STALE | 账户快照过期 | MAX_TOTAL_MARGIN | 超过账户总保证金上限 |
POSITION_SNAPSHOT_MISSING / POSITION_STALE | 持仓快照缺失 / 过期 | AVAILABLE_FUNDS_INSUFFICIENT | 可用资金不足开仓保证金 |
QUOTE_MISSING / QUOTE_STALE | 行情缺失 / 过期 | MARGIN_RATIO_MISSING | 无保证金率与每手保证金 |
PRICE_TICK_MISSING / PRICE_TICK_MISALIGNED | 最小变动价位缺失 / 价格未对齐 | RISK_RATIO_MISSING / MAX_RISK_RATIO | 风险度缺失 / 超限 |
VOLUME_MULTIPLE_MISSING | 合约乘数缺失 | MARGIN_DATA_MISSING | 账户保证金字段缺失 |
DAILY_LIMIT_MISSING / PRICE_OUTSIDE_DAILY_LIMIT | 涨跌停缺失 / 价格越界 | MAX_DAILY_ORDERS / MAX_DAILY_CANCELS | 当日委托 / 撤单次数用尽 |
REFERENCE_PRICE_MISSING / PRICE_DEVIATION_EXCEEDED | 最新价缺失 / 偏离超限 | MAX_DAILY_LOSS | 当日亏损超限 |
MAX_ORDER_VOLUME | 超过单笔手数上限 | MAX_INSTRUMENT_POSITION / MAX_TOTAL_POSITION | 单合约 / 总持仓超限 |
ACTIVE_ORDER_CONFLICT | 该合约存在在途委托 | MODE_MISMATCH | 请求模式与 Worker 不一致 |
TRADING_HALTED | 已熔断 | RECONCILIATION_REQUIRED | 需要对账 |
ADAPTER_STALE | Adapter 心跳不新鲜 | PROFILE_INVALID | 非观察模式下 Profile 无效 |
MARGIN_POLICY_MISMATCH | Worker 与 Adapter 的保证金策略代次或哈希不一致 | AUTO_MARGIN_POLICY_MISMATCH | 自动模式的保证金策略握手不一致 |
AUTO_PERMIT_REQUIRED | LIMITED_AUTO 无生效许可 | EXPLICIT_OFFSET_REQUIRED / POSITION_INSUFFICIENT | 平今昨策略不允许 / 可平量不足 |
LIMITED_AUTO 健康原因(health_reasons)
| reason | 含义 |
|---|---|
AUTO_MODE_NOT_ENABLED | Worker 不在 LIMITED_AUTO 模式 |
AUTO_TRADING_HALTED | 已熔断 |
AUTO_RECONCILIATION_REQUIRED | 需要对账 |
AUTO_ADAPTER_NOT_READY | 心跳缺失、非 READY 或超过 auto_heartbeat_max_age_seconds |
AUTO_ADAPTER_MODE_MISMATCH / AUTO_ADAPTER_PROTOCOL_MISMATCH | Adapter 模式不一致 / 协议版本不是 1 |
AUTO_MARGIN_POLICY_MISMATCH | Worker 与 Adapter 的保证金策略代次或哈希不同 |
AUTO_PROFILE_INVALID | 心跳中 Profile 状态非 VALID |
AUTO_ADAPTER_LOCALLY_HALTED / AUTO_ADAPTER_LOCALLY_PAUSED | Adapter 侧本地熔断 / 本地暂停 |
AUTO_ACCOUNT_SNAPSHOT_STALE / AUTO_POSITION_SNAPSHOT_STALE | 账户 / 持仓快照过期 |
AUTO_DEAD_LETTER_PRESENT | 死信队列存在未处理消息 |
AUTO_QUEUE_BACKLOG | commands 队列深度超过 auto_max_queue_depth |
AUTO_SUBMIT_UNKNOWN_PRESENT | 存在结果未知的提交 |
AUTO_CONSECUTIVE_FAILURE_LIMIT | 连续失败达到许可上限 |
限流与配额
Bridge 是本机回环服务,没有公网 API 的 QPS 限流,也不返回 X-RateLimit-* 头与 429。
取而代之的是一整套本地配额与时效门禁:任何一项超限都会直接拒绝请求,而不是排队或降级。
| 配额项 | 默认值 / 范围 | 超限表现 |
|---|---|---|
| 请求体大小 | max_message_bytes = 65536(1024–16777216) | INVALID_REQUEST · invalid request size |
| 绑定地址 | 必须为回环地址(默认 127.0.0.1:17662) | 配置阶段 CONFIG_ERROR,Worker 拒绝启动 |
| Adapter 心跳时效 | auto_heartbeat_max_age_seconds = 15(5–60) | ADAPTER_STALE / AUTO_ADAPTER_NOT_READY |
| 账户 / 持仓快照时效 | max_snapshot_age_seconds(默认 15) | ACCOUNT_SNAPSHOT_STALE / POSITION_STALE |
| 行情快照时效 | max_quote_age_seconds(默认 10) | QUOTE_STALE |
| 预览有效期 | preview_ttl_seconds(默认 60) | PREVIEW_EXPIRED |
| 指令有效期 | command_ttl_seconds(默认 30) | 消息侧 MESSAGE_EXPIRED |
| 当日委托 / 撤单 | max_daily_orders / max_daily_cancels | MAX_DAILY_ORDERS / MAX_DAILY_CANCELS |
| 许可期笔数 | max_orders(≤ 账户 max_auto_orders) | AUTO_POLICY_REJECTED |
| 两笔最小间隔 | min_order_interval_seconds(≥ 配置下限) | AUTO_POLICY_REJECTED |
| 并发在途单 | max_concurrent_orders | AUTO_POLICY_REJECTED |
| 会话累计名义 | max_session_notional | AUTO_POLICY_REJECTED |
| 单合约持仓名义 | max_instrument_position_notional | AUTO_POLICY_REJECTED |
| 账户回撤 | max_account_drawdown | AUTO_ACCOUNT_DRAWDOWN_EXCEEDED |
| 连续失败 | max_consecutive_failures(1–100) | AUTO_STRATEGY_REAUTHORIZATION_REQUIRED |
| 队列深度 | auto_max_queue_depth = 20 | AUTO_QUEUE_BACKLOG |
| 列表分页 | limit 1–500;instruments ≤ 100 | INVALID_REQUEST |
| 许可时长 | minutes 1–720,且 ≤ max_auto_authorization_minutes | INVALID_REQUEST |
建议的重试策略
仅对确定未送达的失败做指数退避重试:0.5s → 1s → 2s → 4s,最多 4 次;每次重试都要重新同步快照并重新生成预览。
禁止自动重发的场景
PRE_SUBMIT、SUBMIT_CALLED、SUBMIT_UNKNOWN 一律不得自动重发——先读 get_trade_intent 与柜台实际状态,再人工决定。
熔断后停止一切重试
收到 TRADING_HALTED 应立即停止所有交易类调用;熔断只能由本机 Console 解除,解除后强制回到 OBSERVE_ONLY。
import time
from workbuddy_pythongo.errors import BridgeError
NO_RETRY = {"PRE_SUBMIT", "SUBMIT_CALLED", "SUBMIT_UNKNOWN",
"TRADING_HALTED", "LOCAL_CONFIRMATION_REQUIRED"}
def submit_with_retry(core, trade_request, attempts=4):
delay = 0.5
for _ in range(attempts):
try:
preview = core.preview_trade(trade_request)
if not preview["risk"]["allowed"]:
raise BridgeError("RISK_REJECTED", "preview rejected",
{"reasons": preview["risk"]["reasons"]})
return core.submit_trade_intent(preview["preview_id"])
except BridgeError as exc:
if exc.code in NO_RETRY:
raise
core.request_sync(trade_request["account_alias"],
["ACCOUNT", "POSITION", "QUOTE"],
[trade_request["instrument"]],
purpose="TRADE")
time.sleep(delay)
delay *= 2
raise RuntimeError("重试次数用尽")
版本与变更
版本号遵循 Semantic Versioning。当前文档对应 0.3.8;破坏性变更会通过主版本号发布,并在发布说明中给出迁移步骤。
0.3.8 — Windows 快捷方式兼容修复(当前)
- 包含 0.3.7 的全部低延迟异步交易链路改造
- 桌面 CMD 使用 UTF-8,并切换到代码页 65001
- 英文区域设置也可保存中文提示和中文路径
0.3.7 — 低延迟异步交易链路
- 提交可靠入队后立即返回 async_status,通过 get_trade_intent 异步追踪
- Worker 与 Adapter 使用 100–200ms 自适应扫描
- Adapter 启动时预订阅账户白名单合约
- purpose=TRADE 禁止把 KLINE 放入交易热路径
- 撤单与部分成交后撤单聚合为明确终态
0.3.6 — 开箱使用 P0/P1 修复
- 稳定 runtime 自动复用,并可发现 WorkBuddy MCP 与无限易策略目录
- 首次绑定使用 SETUP_LOCK;查询可直接使用,P0 只在启用交易时需要
- P0 合约和单次隔离额度改为短时签名命令动态绑定
- 中文状态与 doctor 给出原因和下一步;Windows CI 覆盖 Python 3.10–3.14
0.3.5 — 配置与状态体验
- Windows 发布包继续使用原有 CMD 一键安装方式,并从包内 wheel 安装 Bridge
- 投资者账号使用便于核对的明文输入,并明确提示它不是密码
- 升级向导自动补齐无风险的保证金策略跟踪字段,实质变化继续要求人工复核
- 健康接口区分连接、观察与交易就绪度,交易保护不再伪装成查询链路故障
0.3.4 — 显式保证金策略迁移
- 日常参考数据刷新不再修改 Adapter 配置、Profile、模式、熔断或授权
- 新增
migrate-margin-policy,旧配置只在本机明确确认后迁移 - Worker 与 Adapter 通过保证金策略代次和哈希握手,不一致时失败关闭
- 实质策略变化保留 Profile,同时熔断、撤销授权并使未消费 Preview 失效
0.3.3 — 整理版本
- 从已验证可运行的 0.3.2 wheel 恢复标准
src/源码结构 - 移除 4 个未使用导入,不改变交易、风控、队列或授权行为
- Worker 的 HTTP 版本标识改为复用包版本,避免发布时重复维护
- 安装器在同目录存在多个 wheel 时明确失败,避免误装旧版本
- 发布脚本改为从
pyproject.toml读取版本,并在构建前清理同项目旧产物 - 清理公开文档中的制作电脑绝对路径,补齐 GitHub 协作、安全与 CI 文件
- 新增 wheel、安装 ZIP、独立 ZIP 哈希与总哈希的一键构建和内容校验
0.3.2 — 保证金参考与资金校验
- 新增九期网保证金 / 手续费参考表按需更新与签名校验
- 新增本机刷新时效硬门禁与源页面时间软告警
- Worker 与 Adapter 基于每手保证金的双重开仓资金校验
- 本地参考数据格式迁移时的失败关闭、Profile 重置与 P0 复验流程
- 默认模式保持
OBSERVE_ONLY;参考缺失、过期、哈希不一致或验签失败时拒绝回退保证金
兼容性承诺
| 层面 | 承诺 |
|---|---|
| MCP 工具 | 31 个工具名与 inputSchema 在 0.3.x 内保持稳定;新增字段只做可选扩展 |
| RPC 信封 | ok / request_id / as_of / data / warnings / error 六字段结构不变 |
| 错误码 | 已有 error.code 语义不变;新增错误码只增不改 |
| 运行模式 | 旧模式名仍可通过迁移映射读取(见运行模式),但会在未来主版本中移除 |
| 队列协议 | protocol_version 为 1.0;Worker 与 Adapter 必须同版本部署 |
Python 模块 API
除 RPC 方法外,包内还直接暴露以下可复用的类与函数。所有模块均位于 workbuddy_pythongo 包下,Python ≥ 3.10。
核心对象
| 对象 | 签名 / 关键成员 | 说明 |
|---|---|---|
BridgeCore | BridgeCore(config, database, keyring, file_queue, ingester) | 全部 31 个方法的实现体;call(method, params) 提供按名分派 |
build_runtime | build_runtime(config_path=None, require_margin_policy=True) -> (config, database, core) | 加载配置、核对保证金策略代次、初始化数据库、队列与事件摄取,返回可直接使用的 core |
load_config | load_config(path=None) -> BridgeConfig | 读取并强校验 bridge.json;路径缺省取 WORKBUDDY_PYTHONGO_CONFIG |
BridgeConfig | path, data_dir, host, port, default_mode, max_message_bytes, key_file, worker_token_file, accounts;account(alias) | 冻结数据类;account() 在别名不存在或未启用时抛 ACCOUNT_NOT_FOUND |
AccountConfig | alias, account_type, adapter_instance, enabled, investor_fingerprint, instrument_allowlist, close_policy, risk_limits;instrument_allowed(exchange, instrument_id) | 白名单为空表示不限制 |
RiskLimits | 见 get_risk_limits 的 23 个字段 | 冻结数据类,配置缺失时使用 AUTO_RISK_DEFAULTS |
错误与模式
| 对象 | 签名 | 说明 |
|---|---|---|
BridgeError | BridgeError(code, message, details=None) | 可安全穿过本机 RPC 边界的结构化错误;属性 code/message/details |
ValidationError | ValidationError(message, details=None) | BridgeError 子类,code 恒为 INVALID_REQUEST |
RUN_MODES | ("OBSERVE_ONLY","SIM_SIGNAL","MANUAL_LIVE","LIMITED_AUTO") | 四种运行模式 |
normalize_mode | normalize_mode(value, allow_legacy=False) | 模式归一化;allow_legacy=True 时接受旧模式名 |
安全与队列
| 对象 | 签名 | 说明 |
|---|---|---|
KeyRing | KeyRing.load(path)、sign(message)、verify(message)、fingerprint_investor(investor_id) | HMAC-SHA256 消息密钥环;密钥长度必须 ≥ 256 bit |
make_envelope | make_envelope(keyring, message_type, payload, ttl_seconds, sender, correlation_id=None) | 生成带 issued_at/expires_at/key_id/signature 的签名信封 |
validate_envelope | validate_envelope(envelope, keyring, expected_types=None, max_clock_skew_seconds=5) | 字段集、协议版本、类型、签名、时效与时钟偏移全量校验 |
FileQueue | write(adapter_instance, folder, envelope)、consume(adapter_instance, folder, handler, expected_types=None, limit=100)、depths(adapter_instance) | 原子写入的签名文件队列;文件夹为 commands/command_acks/events/control/control_acks/archive/dead_letter |
期货语义与工具函数
| 函数 | 签名 | 说明 |
|---|---|---|
validate_trade_request | validate_trade_request(request) -> dict | 严格校验并归一化交易请求(字段集、枚举、数值范围) |
build_preview | build_preview(request, account_config, account_snapshot, position, quote, active_orders, daily_counts) | 纯函数式预览构造:拆分 + 硬风控 + 决策材料与指纹 |
split_order | split_order(action, volume, position, close_policy) | 今昨仓拆分;不足时抛 POSITION_INSUFFICIENT |
age_seconds | age_seconds(timestamp) -> float | 快照年龄,用于新鲜度门禁 |
SignalEngine | moving_average_cross(bars, fast, slow)、persist(..., ttl_seconds=300, cooldown_seconds=60) | 确定性信号:双均线交叉 + 内容哈希去重 + 冷却期 |
| util 工具集 | utc_now、iso_now、parse_time、hash_json、json_text、strict_json_loads、new_id、new_client_order_key、memo_token、normalize_instrument、atomic_write_json、safe_relative_name | 时间、哈希、ID、原子写入与名称安全校验 |
from workbuddy_pythongo.config import load_config
from workbuddy_pythongo.db import Database
from workbuddy_pythongo.file_queue import FileQueue
from workbuddy_pythongo.security import KeyRing
from workbuddy_pythongo.core import BridgeCore
config = load_config("config/bridge.json")
database = Database(config.data_dir + "/state/bridge.db")
database.initialize(config.default_mode)
keyring = KeyRing.load(config.key_file)
queue = FileQueue(config.data_dir, keyring, config.max_message_bytes)
core = BridgeCore(config, database, keyring, queue, ingester=None)
print(core.get_risk_limits("main_futures")["max_daily_orders"])
BridgeCore 只适合只读场景与测试。交易路径请使用 build_runtime() 或官方 Worker 进程,否则队列循环、对账与租约续期不会被驱动。命令行入口
包内提供四个可执行模块。模式切换、Profile 签名与解除熔断只在 Console 中提供,MCP / HTTP 侧无法完成。
| 命令 | 说明 |
|---|---|
python -m workbuddy_pythongo.desktop setup --root <dir> | 中文配置向导,生成失败关闭的部署目录 |
python -m workbuddy_pythongo.manager init|doctor|status | 初始化部署、体检、查看健康状态 |
python -m workbuddy_pythongo.manager start --mode <MODE> --confirm | 切换模式后启动 Worker;非观察模式必须带 --confirm-mode |
python -m workbuddy_pythongo.manager set-mode <MODE> --confirm | 切换运行模式 |
python -m workbuddy_pythongo.manager clear-halt --confirm CLEAR-HALT | 解除熔断(解除后强制回到 OBSERVE_ONLY) |
python -m workbuddy_pythongo.manager sign-profile <alias> --confirm VERIFIED-PROFILE | 校验并签名账户 Profile |
python -m workbuddy_pythongo.manager refresh-margin-reference [--source-csv …] [--if-due] | 刷新本地保证金 / 手续费参考表 |
python -m workbuddy_pythongo.manager migrate-margin-policy --confirm MIGRATE-MARGIN-POLICY | 显式迁移保证金策略配置;实质变化会触发熔断但保留 Profile |
python -m workbuddy_pythongo.worker --config <path> [--confirm-mode <MODE>] | 直接启动回环 Worker |
python -m workbuddy_pythongo.mcp_server --config <path> | 以 stdio 方式提供 MCP 服务(供 WorkBuddy 调用) |
python -m workbuddy_pythongo.console … | Console 子命令:status、set-mode、halt、clear-halt、bind-investor、sign-profile、approve-preview、audit、p0-test-order、p0-validation-leg |
core.py、mcp_server.py、worker.py、config.py、futures.py、security.py 等)与 CHANGELOG 编写,页面完全自包含、无任何外链。
免责声明:本项目能够触发模拟或真实资金账户的委托,不构成投资建议,也不保证盈利。默认模式为
OBSERVE_ONLY;
任何非观察模式都必须先在目标无限易、PythonGO、柜台和账户组合上完成 P0 现场验收。模式名称本身不能证明当前连接的是模拟柜台。
使用本桥接器产生的任何交易结果由使用者自行承担。