常见问题 FAQ

认证、配置与网络

如何获取 Tiger ID、私钥和账户号

登录开发者中心,页面上可直接看到 Tiger ID。点击「生成密钥」即可生成密钥对,下载配置文件(tiger_openapi_config.properties),其中包含 tiger_idprivate_keyaccount 等字段。账户号也可在老虎 APP「我的-账户管理」中查看。


Python 用什么格式的私钥?Java 呢?

各 SDK 都推荐用 PKCS#8 格式的私钥。

开发者中心生成密钥时,可分别下载两种格式。如需手动转换:

# PKCS#1 转 PKCS#8
openssl pkcs8 -topk8 -inform PEM -in private_pkcs1.pem -outform PEM -nocrypt -out private_pkcs8.pem

# PKCS#8 转 PKCS#1
openssl rsa -in private_pkcs8.pem -out private_pkcs1.pem

# 从私钥导出公钥
openssl rsa -in private_pkcs1.pem -pubout -out public_key.pem

API 的服务器地址是什么?

SDK 已内置服务端地址(openapi.tigerfintech.com),无需手动配置。


报错 failed to verify signature / sign check error(code=1000)

可能原因

  1. 私钥不正确
  2. 私钥与开发者中心已上传的公钥不匹配(如重新生成了密钥但请求时未替换为最新密钥)
  3. Windows 路径中反斜杠被当作转义字符

排查步骤

  1. 确认私钥文件是否正确
  2. 开发者中心重新生成密钥对,更新本地私钥
  3. Windows 用户:路径字符串前加 r 前缀,如 r'C:\Users\Foo\Desktop\rsa_private_key.pem'

报错 ValueError: Unable to read this file, version 136 != 0

原因:私钥格式不正确。

解决方法:在开发者中心按 SDK 需要的格式重新复制私钥。可通过文件头判断格式:

格式文件头
PKCS#1-----BEGIN RSA PRIVATE KEY-----
PKCS#8(各 SDK 推荐)-----BEGIN PRIVATE KEY-----

报错 Could not deserialize key data

原因:本地安装的 cryptography 版本与当前 SDK 不兼容(例如 45.x)。

解决方法:降级到兼容版本:

pip install cryptography==42.0.8

报错 request sign failed. int() argument must be a string

原因:私钥格式不正确,或密钥内容没有完整复制。

解决方法:在开发者中心重新生成密钥对,并完整复制私钥内容。


报错 OSError: [Errno 22] Invalid argument(Windows 路径转义)

同类报错还有 request sign failed. Short octet stream on tag decoding

原因:Windows 路径中的反斜杠 \ 被当作转义字符。

解决方法:路径字符串前加 r 前缀使用原始字符串,或改用正斜杠:

client_config.private_key = read_private_key(r'C:\Users\Foo\Desktop\rsa_private_key.pem')
# 或
client_config.private_key = read_private_key('C:/Users/Foo/Desktop/rsa_private_key.pem')

报错 public key error(code=1000)

原因tiger_id 未正确传到服务端。

解决方法:确认 client_config.tiger_id开发者中心显示的 Tiger ID 一致,且没有多余空格或换行符。


报错 failed to get developer information(code=1000)

原因:Tiger ID 不存在。

解决方法:确认 tiger_id 正确。


报错 unauthorized: Please login in(code=1200)

可能原因

  1. tiger_idaccount 不属于同一个开发者账号
  2. 机构用户:该子账户未在机构后台 API 权限中授权

解决方法:机构用户联系管理员在机构中心的 API 权限管理中添加该账户。


报错 account is not authorized to the api user

原因account 字段填写有误,或与当前 tiger_id 不匹配。

账号格式

账户类型账号格式
综合账户(实盘)5~10 位数字
环球账户(实盘)U 开头
模拟账户17 位数字

报错 SSL: CERTIFICATE_VERIFY_FAILEDresponse sign verify failed

可能原因

  1. 将自己生成的公钥错误地填入了 tiger_public_key 字段(该字段由 SDK 内部管理,用户不应修改)
  2. Python 安装时未包含根证书(Mac 通过安装包方式安装的 Python 常见)
  3. 系统 SSL 证书过期或缺失

解决方法

  • 方法一(最推荐,Mac 通过安装包安装 Python 时):打开 应用程序/Python x.x/,双击运行 Install Certificates.command
  • 方法二:安装证书库:pip install certifi,仍未解决则:pip install pip-system-certs
  • 方法三(临时调试,不推荐用于生产)
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
⚠️

方法三会跳过 SSL 证书验证,存在中间人攻击风险,仅建议在本地调试阶段临时使用。


报错 unable to get local issuer certificate

原因:本地缺少根证书库。

解决方法

pip install certifi
# 仍未解决则
pip install pip-system-certs

Mac 用户也可运行 应用程序/Python x.x/Install Certificates.command


报错 module 'http.client' has no attribute 'HTTPConnection'

原因:系统未安装 OpenSSL,或 Python 编译时未链接 OpenSSL。

解决方法:先确认 OpenSSL 可用:

python -c "import ssl; print(ssl.OPENSSL_VERSION)"

若报错,则重新安装 Python 并确保链接了 OpenSSL。


报错 stomp.exception.ConnectFailedException(长连接建立失败)

可能原因

  1. 服务端临时故障
  2. 网络不可达或被防火墙拦截
  3. SSL 配置问题

排查步骤

  1. 检查网络连通性
  2. 确认 PushClientuse_ssl 参数没有被设为 False(默认为 True
  3. 稍后重试;持续失败请联系客服

报错 Unknown response frame type: '' (frame length was 3)

原因PushClient 初始化时设置了 use_ssl=False,导致通信协议不匹配。

解决方法:移除 use_ssl=False 参数,使用默认 SSL 连接。


报错 OSError: [WinError 10038](Windows,非套接字操作)

原因:在长连接断线重连尚未完成时就调用了推送方法(如 query_subscribed_quote)。

解决方法:在 on_connected 回调中执行操作,或调用前先检查连接状态:

if push_client.is_connected():
    push_client.query_subscribed_quote()

连接 code=4001 kick out by a new connection

原因:同一 Tiger ID 同时建立了多个长连接,新连接会踢出旧连接。

说明:同一 Tiger ID 下的模拟账户和实盘账户共用同一个 WebSocket 长连接。如需在一个连接中同时操作两个账户,在同一个 PushClient 实例中分别订阅不同 account 的数据即可。


行情

各市场行情权限说明

市场权限名称内容
美股L1(Nasdaq Basic)纳斯达克实时报价、买卖各 1 档盘口、逐笔成交
美股L2(Nasdaq Totalview)纳斯达克 40 档深度盘口
港股BMP手动刷新行情,仅实时报价,无盘口数据
港股L2自动推送实时报价、买卖 10 档盘口、逐笔成交及经纪队列
美股期权L116 个交易所最优买卖报价及逐笔成交
港股期权L2随港股期货交易所 L2 一同提供(不单独售卖)
期货L2实时报价、买卖 10 档深度、逐笔成交(L1 包含在 L2 内,不单独售卖)

历史行情和推送订阅的额度(K 线数量、可订阅标的数量)根据账户资产或历史成交额自动升级,满足对应条件即可:

条件(满足其一即可)股票/ETF期货期权标准行情订阅摆盘行情订阅
开通 API2010102010
总资产 > 1 万 USD 或成交额 > 10 万 USD2002020010020
总资产 > 5 万 USD 或成交额 > 50 万 USD50050500500100
总资产 > 50 万 USD 或成交额 > 200 万 USD100010010001000200
总资产 > 100 万 USD 或成交额 > 500 万 USD200020020002000500

综合账户付费了美股 L2,模拟账户也能用吗?

是的。行情权限关联到 tiger_id,与账户无关。


美股期权 L1 权限在哪里开通?

老虎证券 APP 内「行情商城」购买。购买后 API 自动生效,可调用 get_option_briefsget_option_chainget_option_trade_ticksget_option_bars 等期权行情接口。


多台设备可以同时使用行情吗?

行情权限同时只有一台设备可持有。多设备使用时需调用 grab_quote_permission() 抢占。如需部署多台机器,建议只在一台机器上创建 QuoteClient(行情);交易接口(TradeClient)不受此限制,多台机器可同时下单。


行情推送退订报错 According to your user level, you can only unsubscribe after 1 minute

原因:订阅后需等待至少 1 分钟才能退订,这是行情服务的限制。

解决方法:在上次订阅操作后等待 1 分钟再调用退订。


financial_report / stock_fundamental 接口报权限错误

get_financial_reportget_stock_fundamentalget_financial_daily 等基本面数据接口需要额外开通权限,默认不开通

开通方式:联系客服申请。Java SDK 对应接口为 QuoteFinancialReportRequestQuoteStockFundamentalRequest,权限要求相同。


如何获取盘前盘后行情和夜盘行情?

  • 盘前/盘后get_stock_briefs(symbols, include_hour_trading=True)get_bars 时指定 trade_session=TradingSession.PreMarket / AfterHours
  • 夜盘(Overnight):需要额外购买 usOvernight 权限,使用 get_bars(..., trade_session=TradingSession.OverNight)
  • 盘前/盘后 K 线:仅支持 2024 年 4 月后的 60 分钟及以下级别数据

get_bars 历史数据支持多久?限制是什么?

周期历史数据范围
分钟(1/5/15/30/60 分钟)近 10 年(需使用 date 参数逐日查询)
日 K 及以上(日/周/月/年)完整历史

单次请求最多返回 1200 条记录。使用 begin_time / end_time 区间查询时有额外限制:1 分钟及 5 分钟 K 线仅支持近 1 个月,15/30/60 分钟 K 线仅支持近 1 年。如需更早的分钟级 K 线,请改用 date 参数按日期逐步查询。


get_bars 支持复权吗?如何选择?

支持,通过 right 参数控制:

参数值含义
QuoteRight.BR(默认)前复权
QuoteRight.NR不复权

接口直接返回复权后的价格,不单独提供复权因子。


get_trading_calendar 支持查几年的数据?

提供2015 年至本年度末的市场交易日历(排除周末及法定节假日,未排除临时休市日期)。可指定市场(Market.US / Market.HK / Market.CN)和日期范围。


逐笔成交中 tickType* 是什么意思?

* 表示中性成交,即当笔成交无法判断是主动买入还是主动卖出(通常发生在成交价正好等于买卖盘口中间价时)。+ 表示主动买入,- 表示主动卖出。


逐笔成交中的 sn 字段是唯一的吗?

sn(序列号)在同一标的的同一交易日内单调递增,可用于判断消息顺序和本地去重。跨标的或跨交易日的 sn 不具备可比性。


逐笔成交的 partCode 是什么意思?

partCode 表示美股成交发生的交易所代码,常见对应关系:

partCode交易所
nNYSE(纽约证券交易所)
tNSDQ(纳斯达克)
pARCA(纽交所 Arca)
zBZX(Cboe BZX)
kEDGX(Cboe EDGX)
vIEX
dADF(FINRA)

完整映射见 SDK 中的 tigeropen.common.consts.tick_constants.PART_CODE_MAP


如何接收实时行情、订单状态、资产变动推送?

使用 PushClient 建立 WebSocket 长连接,通过回调函数(Callback)处理推送数据,无需轮询:

from tigeropen.push.push_client import PushClient
from tigeropen.tiger_open_config import TigerOpenClientConfig

client_config = TigerOpenClientConfig(props_path='your_config_directory_path')
protocol, host, port = client_config.socket_host_port
push_client = PushClient(host, port, use_ssl=(protocol == 'ssl'))
push_client.connect(client_config.tiger_id, client_config.private_key)

# 订阅股票行情
push_client.subscribe_quote(['AAPL'])

# 订阅资产变动(默认每5秒推送一次全量快照)
push_client.subscribe_asset(account='你的账户号')

港股期权行情支持推送订阅吗?

支持。使用 push_client.subscribe_option 订阅港股期权行情,需要港股期货交易所 L2 权限(HKEXFuturesQuoteLv2,该权限包含港股期货和港股期权)。数据结构与美股期权类似,包含最新价、买卖盘口、成交量等字段。


期权订阅额度和股票订阅额度是共享的吗?

不共享。标准行情额度对该大类下各类数据分别生效,股票与期权订阅额度分别计算。标准行情与 Level 2 深度行情也作为独立大类分别计数。额度分类和等级上限见行情权限与限制


期权代码(identifier)格式是什么?如何构造?

美股期权 identifier 为 21 位字符串,格式:SYMBOL YYMMDDP/CXXXXXXXX(symbol 与日期之间有两个空格,到期日 6 位,P/C 后面 8 位为行权价 ×1000,不足补零)。

示例:

  • AAPL 190118P00160000 = AAPL,2019-01-18 到期,PUT,行权价 160.0

推荐使用 SDK 工具方法构造,避免手拼格式错误:

from tigeropen.common.util.contract_utils import get_option_identifier

identifier = get_option_identifier('AAPL', '20190104', 'PUT', 134)
# 返回: 'AAPL  190104P00134000'

港股期权 identifier 则通过 get_option_symbols 接口获取,格式不同,不可手动构造。


推送连接断线后,订阅是否需要重新注册?

需要PushClient 断线重连后,之前的订阅不会自动恢复。推荐在 on_connected 回调中重新执行所有订阅操作:

def on_connected(frame):
    push_client.subscribe_quote(['AAPL', 'TSLA'])
    push_client.subscribe_asset(account=client_config.account)
    push_client.subscribe_order(account=client_config.account)

push_client.on_connected = on_connected

断线期间的行情数据不会补发,重连后只能收到重连之后的推送。


账户与交易

get_prime_assetsget_assets 有什么区别?

get_prime_assetsget_assets
适用账户综合账户、模拟账户环球账户(综合账户也可调用但字段多为空)
返回对象PortfolioAccount,含 segments['S'](证券)和 segments['C'](期货)list[PortfolioAccount],含 SecuritySegmentCommoditySegment
推荐场景获取净值、购买力、浮亏、持仓市值环球账户子账户汇总

如果使用综合账户,始终用 get_prime_assets,不要用 get_assets(会有大量空字段)。


如何读取账户总资产和持仓盈亏?

from tigeropen.trade.trade_client import TradeClient
from tigeropen.tiger_open_config import TigerOpenClientConfig

client_config = TigerOpenClientConfig(props_path='your_config_directory_path')
trade_client = TradeClient(client_config)

# 获取综合账户资产
assets = trade_client.get_prime_assets()
# 通过 segments 访问各分段资产(S=证券, C=期货/商品)
net_liq = assets.segments['S'].net_liquidation   # 净值
gross_pos = assets.segments['S'].gross_position_value  # 总持仓市值
# gross_position_value > net_liquidation 说明使用了杠杆

逐个持仓的已实现/未实现盈亏用 get_positions() 读取:

from tigeropen.common.consts import Currency, Market, SecurityType

positions = trade_client.get_positions(
    sec_type=SecurityType.STK,
    currency=Currency.ALL,
    market=Market.ALL,
)
for position in positions:
    print(position.contract.symbol, position.realized_pnl, position.unrealized_pnl)

报错 'PortfolioAccount' object has no attribute 'net_liquidation'

net_liquidation 不是 PortfolioAccount 的直接属性,需通过 segments 字典访问:

assets.segments['S'].net_liquidation  # 证券段净值
assets.segments['C'].net_liquidation  # 期货段净值(如有)

realized_pnl 的币种是什么?

realized_pnl 的币种取决于持仓标的的交易市场:港股持仓为 HKD,美股为 USD。如需统一换算为某种货币,可在调用接口时传入 base_currency='USD' 参数。


如何实时监控持仓盈亏,需要轮询吗?

不需要轮询。使用 PushClient 订阅资产变动推送:

push_client.subscribe_asset(account='你的账户号')
# 服务端默认每 5 秒推送一次全量资产快照,包含当前持仓盈亏

outside_rth=True 对所有订单类型都有效吗?

不是outside_rth(允许盘前盘后交易)仅对**限价单(LMT)**有效:

  • 市价单(MKT):始终只在盘中执行,设置 outside_rth=True 会被忽略
  • 止损单(STP)、跟踪止损单(TRAIL):也只在盘中有效,outside_rth 参数被忽略
  • 附加订单(止损/止盈 order_leg):建议明确设置 outside_rth=False

如需在盘前/盘后下单,必须使用限价单并设置 outside_rth=True

from tigeropen.trade.domain.order import LimitOrder
order = LimitOrder(account=client_config.account,
                   contract=contract,
                   action='BUY',
                   quantity=1,
                   limit_price=150.0,
                   outside_rth=True)

附加订单(止盈/止损)建议显式设置 outside_rth=False,避免在盘前盘后被触发:

from tigeropen.common.util.order_utils import order_leg

profit_taker = order_leg('PROFIT', 180.0, time_in_force='GTC', outside_rth=False)
stop_loss = order_leg('LOSS', 140.0, time_in_force='GTC', outside_rth=False)

get_orders / get_open_orders / get_filled_orders 有什么区别?

方法返回内容注意
get_orders所有状态的订单(可按状态过滤)默认返回当日所有订单;states 参数仅环球账户支持
get_open_orders待成交的订单,包含部分成交但仍挂单的订单部分成交的订单 filled > 0remaining > 0
get_filled_orders有成交记录的订单,包含部分成交后被撤的订单部分成交被撤时状态可能是 CANCELLEDHELD 等,并非一定是 FILLED
get_cancelled_orders已撤销订单,包含部分成交后撤单的订单

典型场景:一个限价单成交了 50 股后被手动撤单——它会同时出现在 get_filled_orders(有成交)和 get_cancelled_orders(被撤)中。


下单必传的字段有哪些?

字段说明
account账户号
symbol证券代码,如 'AAPL''00700'
sec_type合约类型:STK(股票)/ OPT(期权)/ FUT(期货)
action买卖方向:BUY / SELL
order_type订单类型:MKT(市价)/ LMT(限价)/ STP(止损)/ STP_LMT(止损限价)/ TRAIL(跟踪止损)
quantity委托数量
limit_price限价单必填
aux_price止损单必填(触发价)

接口使用说明

使用 nextPageToken 时为什么每次返回的都是同一批数据?

使用 page_token 分页时,每次请求除 page_token 以外的其他参数必须保持不变。若每次修改了其他参数(如 start_timelimit),会导致服务端报错或从头开始返回。

正确用法:

page_token = ''
while page_token is not None:
    response = trade_client.get_orders(page_token=page_token, limit=100)
    orders = response.result
    page_token = response.next_page_token  # 为 None 时表示已获取全部

nextPageToken 存在时表示什么?

nextPageToken 不为空说明后续还有更多数据。即使当前页已返回了等于 limit 数量的数据,只要总数超过 limit,就会有 token。当返回的 next_page_tokenNone 或空时,表示已获取全部数据


get_ordersstart_time / end_time 是按什么时间过滤的?

默认按下单时间(LATEST_CREATED过滤。如果想按最后状态更新时间过滤(例如查询某时间段内成交的订单),需要传 sort_by=OrderSortBy.LATEST_STATUS_UPDATED

from tigeropen.common.consts import OrderSortBy

# 查询 2025-01-01 至今 状态有更新的订单(如成交、撤单等)
orders = trade_client.get_orders(
    start_time='2025-01-01',
    sort_by=OrderSortBy.LATEST_STATUS_UPDATED
)

注意:sort_by 参数仅支持综合账户,环球账户不支持。


接口调用频率有限制吗?

有。按 TigerId + 接口 独立计数,窗口为 60 秒滚动窗口:

等级频率上限代表接口
高频120 次/分钟place_orderget_ordersget_stock_briefsget_trade_ticksget_option_briefs
中频60 次/分钟get_barsget_depth_quoteget_prime_assetsget_positionsget_option_chain
低频10 次/分钟grab_quote_permissionget_symbolsget_market_statusget_trade_rank

触发限流时会返回 HTTP 429 和业务码 5,错误消息会说明限流信息。频繁触发或持续超限有被加入黑名单的风险。


SDK 使用常见问题

输出显示 [5 rows x 9 columns],看不到完整数据

pandas 默认截断输出。在代码开头添加:

import pandas as pd
pd.set_option('display.max_columns', 500)
pd.set_option('display.max_rows', 5000)
pd.set_option('display.width', 5000)

错误代码速查

错误码含义常见原因
0成功
1服务端异常参数无法处理或服务端内部错误
2网络超时网络不稳定,考虑就近部署
4访问拒绝IP 不在白名单 / 签名失败 / 订阅超限 / 机构用户未传 secret_key
5请求频率超限返回 HTTP 429;错误消息包含限流说明
1000公共参数错误签名错误 / tiger_id 有误 / 请求参数格式错误
1010业务参数错误symbol 为空 / 参数格式有误 / sec_type 不支持
1200综合账号交易错误下单时间段不对 / 盘前盘后不能下市价单 / 持仓不足
1300模拟账号交易错误与综合账号类似
4000权限不足K 线时间段超限 / 行情设备多占 / 行情权限不足
4001长连接被踢出新连接建立,旧连接被断开

完整错误代码列表详见错误代码文档


Did this page help you?