- 金融科技
【免费下载链接】tqsdk-python
天勤量化开发包, 期货量化, 实时行情/历史数据/实盘交易
本文围绕 tqsdk-python 中恒生 O32 柜台交易类TqO32与组合账户类O32Account展开,覆盖组合账户的四级结构(用户.基金.资产单元.组合)、六个构造参数及其校验规则、完整的初始化代码示例,并结合仓库源码剖析登录报文、账户唯一标识生成与本地otg_adapter进程的底层连接链路。读完本文后,你能够完成 O32 直连账户的初始化、参数配置,理解其从TqApi到 O32 前置服务器的完整调用关系,并掌握部署时的依赖与环境要求。
功能定位:O32 柜台直连支持
TqO32是 tqsdk 提供的恒生 O32 柜台交易类,支持用户通过直连模式接入恒生 O32 柜台,官方参考文档见 doc/reference/tqsdk.tqo32.rst,产品介绍见 doc/enterprise.rst 的“恒生 O32 柜台连接功能”一节。
关于版本背景:根据 doc/version.rst 的记录,恒生 O32 柜台支持在3.9.4(2026/04/17)版本中新增;当前仓库的tqsdk/__version__.py中版本为3.10.1,且tqsdk_zq_otg依赖包同样要求不低于3.10.1(见后文部署说明)。TqO32属于企业版直连柜台能力的一部分——企业版支持直连 CTP/融航/杰宜斯/恒生 O32 等柜台,与专业版“通过中继连接”的模式相区别(见 doc/enterprise.rst)。
类定义位于 tqsdk/tradeable/otg/tqo32.py,并通过 tqsdk/init.py 从包顶层导出,可以直接from tqsdk import TqApi, TqAuth, TqO32, O32Account使用。
O32Account:四级组合账户的结构与校验
恒生 O32 柜台的账户采用“用户-基金-资产单元-组合”四级结构,tqsdk 用数据类O32Account表达这一结构。源码(tqsdk/tradeable/otg/tqo32.py#L11-L30)如下:
@dataclass class O32Account: user: str # 用户 fund: str # 基金 asset_unit: str # 资产单元 portfolio: str # 组合 def __post_init__(self) -> None: if not isinstance(self.user, str): raise Exception("user 参数类型应该是 str") if not isinstance(self.fund, str): raise Exception("fund 参数类型应该是 str") if not isinstance(self.asset_unit, str): raise Exception("asset_unit 参数类型应该是 str") if not isinstance(self.portfolio, str): raise Exception("portfolio 参数类型应该是 str") @property def user_name(self) -> str: return ".".join([self.user, self.fund, self.asset_unit, self.portfolio])要点说明:
- 四个字段均为必填的
str类型,__post_init__会对每一项做类型校验,任一字段不是字符串会直接抛出Exception; user_name属性将四个字段用.拼接为形如用户.基金.资产单元.组合的完整账户名。这个拼接结果就是后续登录 O32 柜台时使用的user_name,也是 doc/enterprise.rst 中说明的“内部会拼接成用户.基金.资产单元.组合”的实现来源。
TqO32 构造参数与完整示例
TqO32的构造函数签名(tqsdk/tradeable/otg/tqo32.py#L36-L52)及官方文档字符串中给出的参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
account_id | O32Account | O32 组合账户,内部拼接为用户.基金.资产单元.组合 |
password | str | O32 用户密码 |
td_front_url | str | O32 交易前置地址,格式如112.54.165.180:9003 |
mc_front_url | str | O32 查询前置地址,格式如110.54.163.160:8003 |
license_file | str | O32 许可证文件绝对路径 |
auth_code | str | O32 授权码 |
构造函数内部先对account_id做O32Account类型检查、对其余四个参数做str类型检查,并额外要求license_file不能为空字符串(tqsdk/tradeable/otg/tqo32.py#L80-L96)。随后调用父类构造,传入broker_id=""、account_id=account_id.user_name、td_url="zqotg://127.0.0.1:0/trade"——这两个特殊值的含义见后文“底层连接链路”一节。
官方文档字符串中的完整示例(tqsdk/tradeable/otg/tqo32.py#L54-L77):
from tqsdk import TqApi, TqAuth, TqO32, O32Account def create_account(): return TqO32( account_id=O32Account(user="用户", fund="基金", asset_unit="资产单元", portfolio="组合"), password="password", td_front_url="trade_front_host:trade_front_port", mc_front_url="query_front_host:query_front_port", license_file="/path/to/license.dat", auth_code="auth_code", ) with TqApi(account=create_account(), auth=TqAuth("快期账户", "账户密码")) as api: account_info = api.get_account() positions = api.get_position() print("当前账户信息:", account_info) print("当前持仓信息:", positions)文档同时给出两条注意事项(原文见TqO32.__init__docstring 的“注意”部分):
- 使用
TqO32账户需要安装tqsdk_zq_otg包:pip install -U tqsdk_zq_otg; td_front_url、mc_front_url、license_file和auth_code信息需要向柜台方获取。
源码解析:登录请求报文与账户标识生成
登录报文:backend=o32 与 trading_fronts
TqO32重写了基类BaseOtg的_send_login_pack(tqsdk/tradeable/otg/tqo32.py#L113-L124),向交易通道发送如下 JSON 请求:
req = { "aid": "req_login", "backend": "o32", "user_name": self._account_id, # 即 O32Account.user_name 的拼接结果 "password": self._password, "trading_fronts": [self._td_front_url, self._mc_front_url], "license_file_addr": self._license_file, "auth_code": self._auth_code, "app_id": "tqsdk_o32", } await self._td_send_chan.send(req)可以看出 O32 的登录与 CTP/融航等柜台走bid(期货公司代码)字段的模式不同:它以backend: "o32"声明后端类型,并把交易前置与查询前置两个地址一起放入trading_fronts列表,许可证路径和授权码作为license_file_addr、auth_code字段下发,app_id固定为tqsdk_o32。这与 doc/enterprise.rst 中“td_front_url/mc_front_url为柜台方提供的前置地址,license_file为本地许可证文件位置”的描述完全对应。
账户唯一标识:account_key 的生成
tqsdk内部以account_key作为每个账户实例的唯一标识,用于区分多账户模式下不同账户的账户资金、持仓、委托、成交数据。TqO32重写了_get_account_key(tqsdk/tradeable/otg/tqo32.py#L106-L111):
def _get_account_key(self): s = self._broker_id + self._account_id s += self._td_front_url if self._td_front_url else "" s += self._mc_front_url if self._mc_front_url else "" s += self._license_file if self._license_file else "" return hashlib.md5(s.encode('utf-8')).hexdigest()与基类只用broker_id + account_id计算 MD5(tqsdk/tradeable/otg/base_otg.py#L57-L59)相比,O32 把两个前置地址和许可证路径也纳入了哈希输入。从源码结构看,其目的是保证同一组合账户连到不同前置/许可证环境时也能得到不同的account_key,避免数据串号。该 key 在Tradeable.__init__中确定后“只读不写”(见 tqsdk/tradeable/tradeable.py#L14-L18)。
授权信息:tq_direct 特性与自动加账
TqO32还重写了_account_auth属性:
@property def _account_auth(self): return { "feature": "tq_direct", "account_id": self._account_id, "auto_add": True, }在TqApi的账户授权检查逻辑_check_account_auth中(tqsdk/api.py#L3510-L3518),feature: "tq_direct"要求快期账户具备直连特性,auto_add: True则允许该 O32 组合账户被自动追加到授权账号列表中。这解释了为什么 O32 账户可以不在天勤服务端预先登记组合账户名,即可在本地完成直连登录——这是“可以推断”为便于柜台侧动态开户的设计。
底层连接链路:zqotg:// 地址与 otg_adapter 本地进程
TqO32初始化时把td_url设为zqotg://127.0.0.1:0/trade,这个自定义 URL scheme 是整条连接链路的触发点:
- URL scheme 识别:连接建立时,tqsdk/connect.py#L118-L119 检测到
zqotg前缀后创建ZqOtgContext,由该上下文负责解析出真实的交易服务地址。 - 依赖检查:
ZqOtgContext.__init__(tqsdk/zq_otg.py#L30-L43)会尝试导入tqsdk_zq_otg包,缺失时抛出提示使用 TqO32 账户需要安装 tqsdk_zq_otg 包: pip install -U tqsdk_zq_otg的异常;若版本低于3.10.1则提示升级到最新版。 - 启动本地适配器进程:
get_url方法(tqsdk/zq_otg.py#L99-L127)启动tqsdk_zq_otg包内的otg_adapter可执行文件(--mode=cmd),等待其在数据目录下写出port.json文件,然后把zqotg://127.0.0.1:0/trade替换为ws://127.0.0.1:{port}/trade,最终TqConnect通过本地 WebSocket 与otg_adapter通信,由适配器进程完成与 O32 前置(td_front_url/mc_front_url)的实际对接。 - 日志与配置目录:
otg_adapter的每次运行数据目录创建在~/.tqsdk/otg_logs/(每次运行一个带时间戳的目录),配置目录为~/.tqsdk/otg_config/(tqsdk/zq_otg.py#L20-L24)。日志目录超过上限(默认 30 个,可通过环境变量TQ_OTG_MAX_LOG_DIRS调整)时会自动清理 3 天前的旧目录。排查 O32 连接问题时可以查看这些目录。 - 重连处理:
BaseOtg._connect_td(tqsdk/tradeable/otg/base_otg.py#L105-L124)在连接之上包了一层TdReconnectHandler,为交易通道提供断线重连能力,_run启动后第一件事就是await self._send_login_pack()发送上文所述的 O32 登录报文。
对使用者的实际含义是:Python 进程本身并不直接持有 O32 前置连接,本地otg_adapter进程才是与柜台通信的载体,tqsdk负责拉起、寻址(port.json)、数据收发与断线重连编排。
交易与查询接口:TqO32 继承自 FutureMixin
TqO32继承自BaseOtg与FutureMixin(tqsdk/tradeable/otg/tqo32.py#L33),即按期货账户对待,继承FutureMixin(tqsdk/tradeable/mixin.py#L20-L216)提供的四个查询方法:
| 账户实例方法 | 返回 | 说明 |
|---|---|---|
get_account() | Account | 账户资金信息引用,随api.wait_update()更新 |
get_position(symbol=None) | Position/Entity | 指定合约返回持仓对象;不指定返回全部持仓(dict 结构) |
get_order(order_id=None) | Order/Entity | 委托单对象或全部委托单 |
get_trade(trade_id=None) | Trade/Entity | 成交记录对象或全部成交记录 |
这些方法通过_get_obj(api._data, ["trade", self._account_key, ...], ...)从内部数据截面按account_key定位到本账户的数据,与 tqsdk/tradeable/mixin.py#L61-L62 等实现一致。
下单与查询同样可以通过TqApi实例完成,且参数类型上TqO32已被纳入支持范围:UnionTradeable类型别名包含TqO32(tqsdk/api.py#L89),TqApi.__init__的account参数文档中也列出“TqO32:使用恒生 O32 账号”(tqsdk/api.py#L132)。常用接口包括:
api.insert_order(symbol, direction, offset, volume, limit_price=None, ...)(tqsdk/api.py#L1163):发送下单指令,限价/市价、FAK/FOK高级参数均可用,调用后立即返回,请求在下一次wait_update()时发出;api.cancel_order(order_or_order_id)(tqsdk/api.py#L1436):撤单;api.get_account()/api.get_position()/api.get_order()/api.get_trade()(tqsdk/api.py#L1599 起):单账户模式下直接查询本 O32 账户;多账户模式下通过account=参数指定账户实例。
多账户场景下TqO32可以与其他账户类型(TqAccount、TqSim、TqKq等)混合放进TqMultiAccount列表(TqMultiAccount的accounts类型列表中包含TqO32,见 tqsdk/multiaccount.py#L38),各账户的资金/持仓/委托数据按各自的account_key隔离。
部署前提与适用限制
结合源码与文档,使用TqO32前需确认以下条件:
- 安装直连柜台适配包:
pip install -U tqsdk_zq_otg。从3.7.2(2024/09/12)版本起,tqsdk_zq_otg已从 tqsdk 的安装依赖中移除,使用多柜台(含 O32)需要手动安装(见 doc/version.rst 3.7.2 条目);当前代码要求该包版本不低于3.10.1(tqsdk/zq_otg.py#L37-L38)。 - 快期账户需具备直连(
tq_direct)授权:_check_account_auth会校验TqAuth账户是否具备tq_direct特性(tqsdk/api.py#L3510-L3518),这属于企业版直连功能的授权范畴(见 doc/enterprise.rst)。 - 柜台参数向柜台方获取:
td_front_url(交易前置)、mc_front_url(查询前置)、license_file(许可证文件本地绝对路径)、auth_code(授权码)均由 O32 柜台方提供,license_file不能为空。 - 运行环境:
otg_adapter子进程在 Linux 与 Windows 下均有适配(Windows 用subprocess.Popen,POSIX 用asyncio.create_subprocess_exec,见 tqsdk/zq_otg.py#L111-L118),POSIX 平台还会通过LD_LIBRARY_PATH指向tqsdk_zq_otg包内的库目录。 - O32 账户按期货账户处理:
TqO32混入FutureMixin而非StockMixin,且BaseOtg._update_otg_info中对FUTURE类型有assert isinstance(self, FutureMixin)的断言(tqsdk/tradeable/otg/base_otg.py#L91-L95),其账户资金、持仓对象分别为Account/Position(期货语义),平今/平昨等 offset 规则遵循TqApi.insert_order的通用说明。
相关仓库路径索引
- 参考文档页:doc/reference/tqsdk.tqo32.rst
- 核心实现:tqsdk/tradeable/otg/tqo32.py(
TqO32与O32Account定义) - 柜台基类:tqsdk/tradeable/otg/base_otg.py(登录/重连/报文处理)
- 账户查询混入:tqsdk/tradeable/mixin.py(
FutureMixin) - 本地适配器上下文:tqsdk/zq_otg.py(
ZqOtgContext,otg_adapter进程管理) - 连接层:tqsdk/connect.py(
zqotgscheme 识别) - 主 API:tqsdk/api.py(
TqApi下单/查询接口与账户类型约束) - 企业版直连介绍:doc/enterprise.rst
- 版本记录:doc/version.rst
- 金融科技
【免费下载链接】tqsdk-python
天勤量化开发包, 期货量化, 实时行情/历史数据/实盘交易
相关推荐
TqSdk 企业版实战指南:本地多策略拆分与 CTP/融航/O32/迅投多柜台直连详解
TqSdk 企业版实战指南:本地多策略拆分与 CTP/融航/O32/迅投多柜台直连详解 TqSdk 企业版(Enterprise)是 TqSdk 在专业版之外提
金融科技TqJees 杰宜斯资管账户接入指南:tqsdk 多柜台直连交易架构与源码级解析
TqJees 杰宜斯资管账户接入指南:tqsdk 多柜台直连交易架构与源码级解析 在 tqsdk python(天勤量化开发包)中, TqJees 是用于直连杰
金融科技tqsdk-python TqSdk 模块参考指南:从 TqApi 核心接口到账户接入、指标与工具
tqsdk python TqSdk 模块参考指南:从 TqApi 核心接口到账户接入、指标与工具 本文围绕 doc/reference/index.rst h
金融科技
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考